diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index 5dcdc83e..00000000 --- a/babel.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["@babel/preset-typescript", "@babel/preset-react"], - "plugins": [] -} diff --git a/packages/column-components/stories/measured-section.sass b/packages/column-components/stories/measured-section.sass index a6a092df..f6312801 100644 --- a/packages/column-components/stories/measured-section.sass +++ b/packages/column-components/stories/measured-section.sass @@ -1,6 +1,8 @@ //:global // @require "./imported" +@use "sass:color" + #app width: 40em @@ -57,10 +59,10 @@ g.lithology-column use.frame @mixin interval($color) &>.interval-box margin: 0px - background-color: lighten($color, 50%) - border: 2px solid lighten($color, 10%) !important + background-color: color.adjust($color, $lightness: 50%) + border: 2px solid color.adjust($color, $lightness: 10%) !important .interval-label - color: darken($color, 30%) + color: color.adjust($color, $lightness: -30%) .interval &.Blueflower diff --git a/packages/map-interface/package.json b/packages/map-interface/package.json index f294b635..6cb006f5 100644 --- a/packages/map-interface/package.json +++ b/packages/map-interface/package.json @@ -11,7 +11,7 @@ "@macrostrat/hyper": "^2.2.1", "@macrostrat/mapbox-react": "workspace:*", "@macrostrat/mapbox-utils": "workspace:*", - "@macrostrat/ui-components": "workspace:^4.0.1", + "@macrostrat/ui-components": "^4.0.1", "@mapbox/tilebelt": "^1.0.2", "@turf/bbox": "^6.5.0", "chroma-js": "^2.4.2", @@ -19,7 +19,7 @@ "d3-array": "^3.2.4", "d3-format": "^3.1.0", "mapbox-gl": "^2.15.0", - "query-string": "^8.1.0", + "query-string": "^9.0.0", "transition-hook": "^1.5.2", "underscore": "^1.13.6", "use-resize-observer": "^9.1.0" diff --git a/packages/style-system/src/colors.scss b/packages/style-system/src/colors.scss index 1840d435..9031a827 100644 --- a/packages/style-system/src/colors.scss +++ b/packages/style-system/src/colors.scss @@ -42,22 +42,22 @@ $dark-colors: ( color.change($dark-background, $alpha: 0.6), accent-color: $accent, // light gray 3, - accent-secondary-color: lighten($accent, 0%), - accent-secondary-hover-color: lighten($accent, 5%), + accent-secondary-color: $accent, + accent-secondary-hover-color: color.adjust($accent, $lightness: 5%), panel-rule-color: #404854, secondary-color: $gray1, // gray3, - tertiary-background: lighten($accent, 4%), + tertiary-background: color.adjust($accent, $lightness: 4%), // light gray 5, tertiary-color: #383e47, // light gray 4, tertiary-border-color: #5f6b7c, // gray 5, - accent-hover-color: lighten($accent, 4%), + accent-hover-color: color.adjust($accent, $lightness: 4%), // light gray 1, accent-border-color: #5f6b7c, // gray5, card-shadow-color: color.adjust($gray1, $alpha: 0.2), ui-color-accent-text: rgb(252, 217, 250), - ui-color-accent: darken(rgb(143, 39, 138), 50%), + ui-color-accent: color.adjust(rgb(143, 39, 138), $lightness: -50%), ); diff --git a/packages/ui-components/.babelrc b/packages/ui-components/.babelrc deleted file mode 100644 index 346e94ff..00000000 --- a/packages/ui-components/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-react", - "@babel/preset-typescript" - ], - "plugins": [ - "@babel/plugin-proposal-nullish-coalescing-operator", - "@babel/plugin-proposal-optional-chaining", - "@babel/plugin-proposal-class-properties" - ] -} \ No newline at end of file diff --git a/packages/ui-components/.dockerignore b/packages/ui-components/.dockerignore deleted file mode 100644 index 3063f07d..00000000 --- a/packages/ui-components/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -lib -node_modules diff --git a/packages/ui-components/CHANGELOG.md b/packages/ui-components/CHANGELOG.md index 8bceb655..e3de1047 100644 --- a/packages/ui-components/CHANGELOG.md +++ b/packages/ui-components/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [4.0.2] - 2024-10-24 + +- Migrate from `@blueprintjs/datetime` to `@blueprintjs/datetime2` to allow + official React 18 compatibility +- Allow `@macrostrat/hyper` version 3 +- Update `query-string` to version 9 +- Remove unused dependencies, which were mostly present due to speculation on + future needs and desired functionality + - `@mantine/core` + - `@mantine/hooks` + - `io-ts` + - `fp-ts` + - `core-js` + - `date-fns` + - `@emotion/react` + - `@babel/polyfill` +- Create a "development panel" component for use in application debugging +- Remove `init.js` file, which was used to set up global state but is kind of + outmoded. + ## [4.0.1] - 2024-10-02 Bug fix: missing package specifier @@ -8,9 +28,10 @@ Bug fix: missing package specifier - Update BlueprintJS to version 5 - Remove unused script files -- Add an `applySystemDarkMode` function to `DarkModeProvider` to allow the user to apply the system's dark mode setting. -- Add a default validator for local storage items to prevent errors arising - from malformed stored objects. +- Add an `applySystemDarkMode` function to `DarkModeProvider` to allow the user + to apply the system's dark mode setting. +- Add a default validator for local storage items to prevent errors arising from + malformed stored objects. - Broke out position button handling somewhat - Removed duplicate styles @@ -20,9 +41,10 @@ Bug fix: missing package specifier ## [3.1.0] - 2023-04-21 -- Add a `followSystem` option to `DarkModeProvider` to allow the user to follow the system's dark mode setting. -- Add a `Box`, `FlexRow`, `FlexColumn`, and `Spacer` components - to improve layout capabilities. +- Add a `followSystem` option to `DarkModeProvider` to allow the user to follow + the system's dark mode setting. +- Add a `Box`, `FlexRow`, `FlexColumn`, and `Spacer` components to improve + layout capabilities. ## [3.0.0] - August 2022 @@ -40,12 +62,16 @@ Bug fix: missing package specifier ## [1.0.0] - 23-09-2021 - Finally remove deprecated `APIView` component. -- Change `InfiniteScrollView` component to use `IntersectionObserver` APIs, in order to get rid of stale dependency `react-infinite-scroller`. +- Change `InfiniteScrollView` component to use `IntersectionObserver` APIs, in + order to get rid of stale dependency `react-infinite-scroller`. - Add a `useScrollMarkers` hook ## [0.7.0] - 20-09-2021 -- **Breaking change**: Move `LinkCard` and other compents in `ext/router-links` to the new [`@macrostrat/router-components`](https://github.com/UW-Macrostrat/router-components) module. +- **Breaking change**: Move `LinkCard` and other compents in `ext/router-links` + to the new + [ `@macrostrat/router-components`](https://github.com/UW-Macrostrat/router-components) + module. - Add a skeletal data provider that tracks multiple `useAPIResult` calls - Added a default theme (Monokai) to `JSONView` - Added a `ModalPanel` component @@ -53,19 +79,23 @@ Bug fix: missing package specifier ## [0.6.0] - 28-06-2021 -- **Breaking change**: Move `LinkCard` and other components depending on `react-router-dom` to a separate `ext/router-links` section. - This allows applications that don't use `react-router` to still use the bulk of the module +- **Breaking change**: Move `LinkCard` and other components depending on + `react-router-dom` to a separate `ext/router-links` section. This allows + applications that don't use `react-router` to still use the bulk of the module - Move Changelog to a separate file - Upgrade delete button - Added an `ErrorBoundary` component -- Allowed resetting `useStoredState` using a third parameter, as such: `const [state, setState, resetState] = useStoredState(id, initialState)` -- Can now reset dark mode state to default using a `Shift+click` on the `DarkModeButton`. +- Allowed resetting `useStoredState` using a third parameter, as such: + `const [state, setState, resetState] = useStoredState(id, initialState)` +- Can now reset dark mode state to default using a `Shift+click` on the + `DarkModeButton`. ## [0.5.0] - 10-02-2021 -- Move towards using Axios base types for API context. Allows more advanced abilities - to control global request context through Axios's built-in methods. Additional configurability - will be progressively added through the `0.5` series. +- Move towards using Axios base types for API context. Allows more advanced + abilities to control global request context through Axios's built-in methods. + Additional configurability will be progressively added through the `0.5` + series. ## [0.4.4] - 14-11-2020 @@ -76,7 +106,8 @@ Bug fix: missing package specifier ## [0.4.2] - 12-10-2020 - Added `SettingsProvider` and settings context for persistent settings -- Upgraded dark mode context to store values across page reloads (using local storage) +- Upgraded dark mode context to store values across page reloads (using local + storage) ## [0.3.0] - 18-08-2020 diff --git a/packages/ui-components/init.js b/packages/ui-components/init.js deleted file mode 100644 index 28be59f6..00000000 --- a/packages/ui-components/init.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - This file MUST be compiled with Webpack, Parcel, or similar to - work. You may need to copy its contents into your projects initialization - script in order for CSS stylesheets, etc. to resolve properly. -*/ -// Babel polyfills -import "core-js/stable"; -import "regenerator-runtime/runtime"; - -import { FocusStyleManager } from "@blueprintjs/core"; -import "@blueprintjs/core/lib/css/blueprint.css"; -import "./dist/ui-components.css"; - -FocusStyleManager.onlyShowFocusOnTabs(); diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index 3c20d466..47c83917 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -1,7 +1,7 @@ { "name": "@macrostrat/ui-components", - "version": "4.0.1", - "description": "UI components for React and blueprint.js", + "version": "4.0.2", + "description": "UI components for React and Blueprint.js", "main": "dist/main.js", "module": "dist/module.js", "types": "dist/types.d.ts", @@ -16,8 +16,7 @@ ], "files": [ "dist", - "src", - "init.js" + "src" ], "author": "Daven Quinn", "contributors": [ @@ -30,43 +29,26 @@ "access": "public" }, "dependencies": { - "@babel/polyfill": "^7.4.4", "@blueprintjs/core": "^5.10.2", - "@blueprintjs/datetime": "^5.3.4", - "@macrostrat/hyper": "^2.2.1", - "@mantine/core": "^4.1.3", - "@mantine/hooks": "^4.1.3", - "axios": "^1.6.0", - "chroma-js": "^2.4.2", + "@blueprintjs/datetime2": "^2.3.11", + "@macrostrat/hyper": "^2.2.1||^3.0.0", + "axios": "^1.7.7", + "chroma-js": "^2.4.2||^3.0.0", "classnames": "^2.3.0", - "core-js": "^3.6.4", - "d3-array": "^3.0.4", - "date-fns": "^2.15.0", - "fp-ts": "^2.5.3", + "d3-array": "^3.2.4", "immutability-helper": "^3.1.1", - "io-ts": "^2.1.2", - "query-string": "^7.0.0", + "query-string": "^9.0.0", "react-color": "^2.19.3", "react-dropzone": "^11.4.2", "react-intersection-observer": "^8.32.1", - "react-json-tree": "^0.15.0", + "react-json-tree": "^0.19.0", "ui-box": "^5.4.1", - "underscore": "^1.9.1", + "underscore": "^1.13.1", "use-async-effect": "^2.2.1", "use-element-dimensions": "^2.1.3", "zustand": "^4.5.1" }, "devDependencies": { - "@babel/core": "^7.16.12", - "@babel/plugin-proposal-class-properties": "^7.8.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.9.0", - "@babel/plugin-transform-typescript": "^7.11.0", - "@babel/preset-env": "^7.16.11", - "@babel/preset-react": "^7.16.7", - "@babel/preset-typescript": "^7.16.7", - "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-node-resolve": "^13.1.3", "parcel": "^2.12.0" }, "exports": { diff --git a/packages/ui-components/src/api/frontend.ts b/packages/ui-components/src/api/frontend.ts index 4ce3a40d..94dba620 100644 --- a/packages/ui-components/src/api/frontend.ts +++ b/packages/ui-components/src/api/frontend.ts @@ -5,10 +5,8 @@ import { Spinner } from "@blueprintjs/core"; import { APIContext, APIActions, APIHelpers } from "./provider"; import { debounce } from "underscore"; import { APIConfig } from "./types"; -import { QueryParams } from "../util/query-string"; -import { JSONView } from "../util/json-view"; +import { QueryParams, JSONView } from "../util"; import { IndexingProvider } from "./indexing"; -import { number } from "fp-ts"; interface APIPlaceholderProps { isLoading: boolean; @@ -56,9 +54,9 @@ class APIResultView extends Component, APIResultState> { // method will be called with null data placeholder: APIResultPlaceholder, debounce: 300, - children: data => { + children: (data) => { return h(JSONView, { data }); - } + }, }; _didFetch: boolean; _lazyGetData: () => Promise; @@ -117,7 +115,7 @@ class APIResultView extends Component, APIResultState> { } else if (isValidElement(children)) { return cloneElement(children, { data, - isLoading + isLoading, }); } else { throw new Error( @@ -138,7 +136,7 @@ class APIResultView extends Component, APIResultState> { IndexingProvider, { totalCount: data.length, - indexOffset: 0 + indexOffset: 0, }, this.renderInner() ); diff --git a/packages/ui-components/src/model-editor.ts b/packages/ui-components/src/model-editor.ts index af1a1fa9..e338e0ad 100644 --- a/packages/ui-components/src/model-editor.ts +++ b/packages/ui-components/src/model-editor.ts @@ -1,14 +1,14 @@ // @ts-nocheck import { Component, createContext, ReactElement, useContext } from "react"; import h from "@macrostrat/hyper"; -import { DateInput } from "@blueprintjs/datetime"; +import { DateInput3 } from "@blueprintjs/datetime2"; import { EditableText } from "@blueprintjs/core"; import { EditButton, DeleteButton } from "./buttons"; import { StatefulComponent } from "./util"; import classNames from "classnames"; import update, { Spec } from "immutability-helper"; -import "@blueprintjs/datetime/lib/css/blueprint-datetime.css"; +import "@blueprintjs/datetime2/lib/css/blueprint-datetime2.css"; const ModelEditorContext = createContext({}); @@ -40,11 +40,8 @@ class ModelEditor extends StatefulComponent< ModelEditorProps, ModelEditorState > { - static defaultProps = { - canEdit: true, - }; - constructor(props) { - super(props); + constructor({ canEdit = true, ...props }) { + super(...arguments); this.getValue = this.getValue.bind(this); this.hasChanges = this.hasChanges.bind(this); this.onChange = this.onChange.bind(this); @@ -185,7 +182,9 @@ function EditableMultilineText(props: any): React.ReactNode { const { actions, model, isEditing } = useContext(ModelEditorContext); let value = model[field]; const onChange = actions.onChange(field); - className = classNames(className, `field-${field}`); + className = classNames(className, `field-${field}`, { + edited: useFieldHasChanges(field), + }); if (isEditing) { value = h(EditableText, { @@ -199,20 +198,36 @@ function EditableMultilineText(props: any): React.ReactNode { return h("div.text", { className }, value); } +const useFieldHasChanges = (field) => { + const { hasChanges } = useContext(ModelEditorContext); + return hasChanges(field); +}; + class EditableDateField extends Component { static contextType = ModelEditorContext; render() { const { field } = this.props; const { actions, model, isEditing } = this.context; const value = model[field]; + + const className = classNames("date-input", { + edited: this.context.hasChanges(field), + disabled: !isEditing, + }); + + let valueText = value; + if (value instanceof Date) { + valueText = value.toLocaleDateString(); + } + if (!isEditing) { - return h("div.date-input.disabled", value); + return h("div", { className }, valueText); } - return h(DateInput, { - className: "date-input", + return h(DateInput3, { + className, value: new Date(value), formatDate: (date) => date.toLocaleDateString(), - placeholder: "MM/DD/YYYY", + placeholder: valueText ?? "Select date...", showActionsBar: true, onChange: actions.onChange(field), parseDate(d) { diff --git a/packages/ui-components/stories/model-editor.stories.ts b/packages/ui-components/stories/model-editor.stories.ts new file mode 100644 index 00000000..cefa4dc8 --- /dev/null +++ b/packages/ui-components/stories/model-editor.stories.ts @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { + EditableMultilineText, + EditableDateField, + ModelEditor, + ModelEditButton, +} from "../src/model-editor"; +import h from "@macrostrat/hyper"; +import "./stories.sass"; + +import { LngLatCoords, LngLatProps } from "packages/map-interface/src"; + +// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta: Meta = { + title: "UI components/Model Editor", + component: ModelEditorExample, +}; + +export default meta; + +export function ModelEditorExample(props) { + const data = { + title: "Test dataset", + description: + "Taste-testing results for peanut butter and jellyfish sandwiches", + embargoDate: new Date(), + }; + + return h( + ModelEditor, + { + model: data, + canEdit: true, + }, + [ + h("div.model-editor-example", [ + h(EditableMultilineText, { field: "title", className: "title-text" }), + h(EditableMultilineText, { field: "description" }), + h(EditableDateField, { field: "embargoDate" }), + h(ModelEditButton), + ]), + ] + ); +} diff --git a/packages/ui-components/stories/stories.sass b/packages/ui-components/stories/stories.sass new file mode 100644 index 00000000..a0247e16 --- /dev/null +++ b/packages/ui-components/stories/stories.sass @@ -0,0 +1,11 @@ +.model-editor-example + &>*:not(:last-child) + margin-bottom: 1em + + .edited + background-color: lightgreen + +.title-text + font-weight: 600 + font-size: 2em + diff --git a/packages/ui-components/src/toaster.stories.ts b/packages/ui-components/stories/toaster.stories.ts similarity index 90% rename from packages/ui-components/src/toaster.stories.ts rename to packages/ui-components/stories/toaster.stories.ts index 909fc664..6d1047bd 100644 --- a/packages/ui-components/src/toaster.stories.ts +++ b/packages/ui-components/stories/toaster.stories.ts @@ -3,8 +3,12 @@ import { Button } from "@blueprintjs/core"; import type { Meta, StoryObj } from "@storybook/react"; import { useRef } from "react"; -import { ToasterContext, ToasterContextProps, useToaster } from "./toaster"; -import { FlexRow, Box } from "./util"; +import { + ToasterContext, + ToasterContextProps, + useToaster, +} from "../src/toaster"; +import { FlexRow, Box } from "../src/util"; // More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta: Meta = {