diff --git a/.changeset/all-build-dev-dep.md b/.changeset/all-build-dev-dep.md deleted file mode 100644 index e324dfca43..0000000000 --- a/.changeset/all-build-dev-dep.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -'@lg-chat/leafygreen-chat-provider': patch -'@leafygreen-ui/leafygreen-provider': patch -'@leafygreen-ui/confirmation-modal': patch -'@leafygreen-ui/gallery-indicator': patch -'@leafygreen-ui/inline-definition': patch -'@leafygreen-ui/loading-indicator': patch -'@leafygreen-ui/segmented-control': patch -'@lg-tools/storybook-decorators': patch -'@leafygreen-ui/expandable-card': patch -'@leafygreen-ui/marketing-modal': patch -'@leafygreen-ui/radio-box-group': patch -'@leafygreen-ui/skeleton-loader': patch -'@leafygreen-ui/password-input': patch -'@lg-charts/series-provider': patch -'@lg-chat/fixed-chat-window': patch -'@leafygreen-ui/info-sprinkle': patch -'@lg-chat/message-feedback': patch -'@leafygreen-ui/input-option': patch -'@leafygreen-ui/number-input': patch -'@leafygreen-ui/ordered-list': patch -'@leafygreen-ui/search-input': patch -'@leafygreen-ui/split-button': patch -'@lg-tools/storybook-addon': patch -'@lg-tools/storybook-utils': patch -'@lg-charts/drag-provider': patch -'@lg-chat/chat-disclaimer': patch -'@lg-chat/message-prompts': patch -'@leafygreen-ui/date-picker': patch -'@leafygreen-ui/descendants': patch -'@leafygreen-ui/empty-state': patch -'@leafygreen-ui/form-footer': patch -'@leafygreen-ui/icon-button': patch -'@leafygreen-ui/polymorphic': patch -'@leafygreen-ui/radio-group': patch -'@leafygreen-ui/testing-lib': patch -'@lg-tools/test-harnesses': patch -'@lg-chat/message-rating': patch -'@leafygreen-ui/date-utils': patch -'@leafygreen-ui/form-field': patch -'@leafygreen-ui/pagination': patch -'@leafygreen-ui/text-input': patch -'@leafygreen-ui/typography': patch -'@leafygreen-ui/guide-cue': patch -'@leafygreen-ui/text-area': patch -'@lg-charts/chart-card': patch -'@lg-chat/message-feed': patch -'@leafygreen-ui/checkbox': patch -'@leafygreen-ui/combobox': patch -'@leafygreen-ui/copyable': patch -'@leafygreen-ui/pipeline': patch -'@leafygreen-ui/side-nav': patch -'@lg-chat/chat-window': patch -'@lg-chat/lg-markdown': patch -'@leafygreen-ui/callout': patch -'@leafygreen-ui/emotion': patch -'@leafygreen-ui/palette': patch -'@leafygreen-ui/popover': patch -'@leafygreen-ui/stepper': patch -'@leafygreen-ui/tooltip': patch -'@lg-chat/rich-links': patch -'@leafygreen-ui/avatar': patch -'@leafygreen-ui/banner': patch -'@leafygreen-ui/button': patch -'@leafygreen-ui/drawer': patch -'@leafygreen-ui/portal': patch -'@leafygreen-ui/ripple': patch -'@leafygreen-ui/select': patch -'@leafygreen-ui/toggle': patch -'@leafygreen-ui/tokens': patch -'@lg-chat/input-bar': patch -'@lg-chat/title-bar': patch -'@leafygreen-ui/badge': patch -'@leafygreen-ui/hooks': patch -'@leafygreen-ui/modal': patch -'@leafygreen-ui/table': patch -'@leafygreen-ui/toast': patch -'@lg-tools/codemods': patch -'@lg-tools/slackbot': patch -'@lg-tools/validate': patch -'@lg-charts/colors': patch -'@lg-charts/legend': patch -'@leafygreen-ui/a11y': patch -'@leafygreen-ui/card': patch -'@leafygreen-ui/chip': patch -'@leafygreen-ui/code': patch -'@leafygreen-ui/icon': patch -'@leafygreen-ui/logo': patch -'@leafygreen-ui/menu': patch -'@leafygreen-ui/tabs': patch -'@lg-tools/install': patch -'@lg-chat/message': patch -'@leafygreen-ui/box': patch -'@leafygreen-ui/lib': patch -'@lg-tools/create': patch -'@lg-tools/update': patch -'@lg-charts/core': patch -'@lg-chat/avatar': patch -'@lg-tools/build': patch -'@lg-tools/link': patch -'@lg-tools/lint': patch -'@lg-tools/meta': patch -'@lg-tools/test': patch -'@lg-tools/cli': patch -'lg-scripts': patch ---- - -Adds `@lg-tools/build` as a dev dependency diff --git a/.changeset/all-lg-build-dev-dep.md b/.changeset/all-lg-build-dev-dep.md deleted file mode 100644 index 90db392222..0000000000 --- a/.changeset/all-lg-build-dev-dep.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -'@lg-chat/leafygreen-chat-provider': patch -'@leafygreen-ui/leafygreen-provider': patch -'@leafygreen-ui/confirmation-modal': patch -'@leafygreen-ui/gallery-indicator': patch -'@leafygreen-ui/inline-definition': patch -'@leafygreen-ui/loading-indicator': patch -'@leafygreen-ui/segmented-control': patch -'@leafygreen-ui/expandable-card': patch -'@leafygreen-ui/marketing-modal': patch -'@leafygreen-ui/radio-box-group': patch -'@leafygreen-ui/skeleton-loader': patch -'@leafygreen-ui/password-input': patch -'@lg-charts/series-provider': patch -'@lg-chat/fixed-chat-window': patch -'@leafygreen-ui/info-sprinkle': patch -'@lg-chat/message-feedback': patch -'@leafygreen-ui/input-option': patch -'@leafygreen-ui/number-input': patch -'@leafygreen-ui/ordered-list': patch -'@leafygreen-ui/search-input': patch -'@leafygreen-ui/split-button': patch -'@lg-tools/storybook-utils': patch -'@lg-charts/drag-provider': patch -'@lg-chat/chat-disclaimer': patch -'@lg-chat/message-prompts': patch -'@leafygreen-ui/date-picker': patch -'@leafygreen-ui/descendants': patch -'@leafygreen-ui/empty-state': patch -'@leafygreen-ui/form-footer': patch -'@leafygreen-ui/icon-button': patch -'@leafygreen-ui/polymorphic': patch -'@leafygreen-ui/radio-group': patch -'@lg-tools/test-harnesses': patch -'@lg-chat/message-rating': patch -'@leafygreen-ui/date-utils': patch -'@leafygreen-ui/form-field': patch -'@leafygreen-ui/pagination': patch -'@leafygreen-ui/text-input': patch -'@leafygreen-ui/typography': patch -'@leafygreen-ui/guide-cue': patch -'@leafygreen-ui/text-area': patch -'@lg-charts/chart-card': patch -'@lg-chat/message-feed': patch -'@leafygreen-ui/checkbox': patch -'@leafygreen-ui/combobox': patch -'@leafygreen-ui/copyable': patch -'@leafygreen-ui/pipeline': patch -'@leafygreen-ui/side-nav': patch -'@lg-chat/chat-window': patch -'@lg-chat/lg-markdown': patch -'@leafygreen-ui/callout': patch -'@leafygreen-ui/emotion': patch -'@leafygreen-ui/palette': patch -'@leafygreen-ui/popover': patch -'@leafygreen-ui/stepper': patch -'@leafygreen-ui/tooltip': patch -'@lg-chat/rich-links': patch -'@leafygreen-ui/avatar': patch -'@leafygreen-ui/banner': patch -'@leafygreen-ui/button': patch -'@leafygreen-ui/drawer': patch -'@leafygreen-ui/portal': patch -'@leafygreen-ui/ripple': patch -'@leafygreen-ui/select': patch -'@leafygreen-ui/toggle': patch -'@leafygreen-ui/tokens': patch -'@lg-chat/input-bar': patch -'@lg-chat/title-bar': patch -'@leafygreen-ui/badge': patch -'@leafygreen-ui/hooks': patch -'@leafygreen-ui/modal': patch -'@leafygreen-ui/table': patch -'@leafygreen-ui/toast': patch -'@lg-charts/colors': patch -'@lg-charts/legend': patch -'@leafygreen-ui/a11y': patch -'@leafygreen-ui/card': patch -'@leafygreen-ui/chip': patch -'@leafygreen-ui/code': patch -'@leafygreen-ui/icon': patch -'@leafygreen-ui/logo': patch -'@leafygreen-ui/menu': patch -'@leafygreen-ui/tabs': patch -'@lg-chat/message': patch -'@leafygreen-ui/box': patch -'@leafygreen-ui/lib': patch -'@lg-charts/core': patch -'@lg-chat/avatar': patch ---- - -Adds missing `@lg-tools/` devDependencies. -Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli diff --git a/.changeset/all-types-entry-point.md b/.changeset/all-types-entry-point.md deleted file mode 100644 index 24faa81c3a..0000000000 --- a/.changeset/all-types-entry-point.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -'@lg-chat/leafygreen-chat-provider': patch -'@leafygreen-ui/leafygreen-provider': patch -'@leafygreen-ui/confirmation-modal': patch -'@leafygreen-ui/gallery-indicator': patch -'@leafygreen-ui/inline-definition': patch -'@leafygreen-ui/loading-indicator': patch -'@leafygreen-ui/segmented-control': patch -'@lg-tools/storybook-decorators': patch -'@leafygreen-ui/expandable-card': patch -'@leafygreen-ui/marketing-modal': patch -'@leafygreen-ui/radio-box-group': patch -'@leafygreen-ui/skeleton-loader': patch -'@leafygreen-ui/password-input': patch -'@lg-charts/series-provider': patch -'@lg-chat/fixed-chat-window': patch -'@leafygreen-ui/info-sprinkle': patch -'@lg-chat/message-feedback': patch -'@leafygreen-ui/input-option': patch -'@leafygreen-ui/number-input': patch -'@leafygreen-ui/ordered-list': patch -'@leafygreen-ui/search-input': patch -'@leafygreen-ui/split-button': patch -'@lg-tools/storybook-addon': patch -'@lg-tools/storybook-utils': patch -'@lg-charts/drag-provider': patch -'@lg-chat/chat-disclaimer': patch -'@lg-chat/message-prompts': patch -'@leafygreen-ui/date-picker': patch -'@leafygreen-ui/descendants': patch -'@leafygreen-ui/empty-state': patch -'@leafygreen-ui/form-footer': patch -'@leafygreen-ui/icon-button': patch -'@leafygreen-ui/polymorphic': patch -'@leafygreen-ui/radio-group': patch -'@leafygreen-ui/testing-lib': patch -'@lg-tools/test-harnesses': patch -'@lg-chat/message-rating': patch -'@leafygreen-ui/date-utils': patch -'@leafygreen-ui/form-field': patch -'@leafygreen-ui/pagination': patch -'@leafygreen-ui/text-input': patch -'@leafygreen-ui/typography': patch -'@leafygreen-ui/guide-cue': patch -'@leafygreen-ui/text-area': patch -'@lg-charts/chart-card': patch -'@lg-chat/message-feed': patch -'@leafygreen-ui/checkbox': patch -'@leafygreen-ui/combobox': patch -'@leafygreen-ui/copyable': patch -'@leafygreen-ui/pipeline': patch -'@leafygreen-ui/side-nav': patch -'@lg-chat/chat-window': patch -'@lg-chat/lg-markdown': patch -'@leafygreen-ui/callout': patch -'@leafygreen-ui/emotion': patch -'@leafygreen-ui/palette': patch -'@leafygreen-ui/popover': patch -'@leafygreen-ui/stepper': patch -'@leafygreen-ui/tooltip': patch -'@lg-chat/rich-links': patch -'@leafygreen-ui/avatar': patch -'@leafygreen-ui/banner': patch -'@leafygreen-ui/button': patch -'@leafygreen-ui/drawer': patch -'@leafygreen-ui/portal': patch -'@leafygreen-ui/ripple': patch -'@leafygreen-ui/select': patch -'@leafygreen-ui/toggle': patch -'@leafygreen-ui/tokens': patch -'@lg-chat/input-bar': patch -'@lg-chat/title-bar': patch -'@leafygreen-ui/badge': patch -'@leafygreen-ui/hooks': patch -'@leafygreen-ui/modal': patch -'@leafygreen-ui/table': patch -'@leafygreen-ui/toast': patch -'@lg-tools/codemods': patch -'@lg-tools/slackbot': patch -'@lg-tools/validate': patch -'@lg-charts/colors': patch -'@lg-charts/legend': patch -'@leafygreen-ui/a11y': patch -'@leafygreen-ui/card': patch -'@leafygreen-ui/chip': patch -'@leafygreen-ui/code': patch -'@leafygreen-ui/icon': patch -'@leafygreen-ui/logo': patch -'@leafygreen-ui/menu': patch -'@leafygreen-ui/tabs': patch -'@lg-tools/install': patch -'@lg-chat/message': patch -'@leafygreen-ui/box': patch -'@leafygreen-ui/lib': patch -'@lg-tools/create': patch -'@lg-tools/update': patch -'@lg-charts/core': patch -'@lg-chat/avatar': patch -'@lg-tools/build': patch -'@lg-tools/link': patch -'@lg-tools/lint': patch -'@lg-tools/meta': patch -'@lg-tools/test': patch -'@lg-tools/cli': patch ---- - -Updates `types` entry point to `./dist/types`. -Removes redundant `compilerOptions` from TSConfig diff --git a/.changeset/all-umd-entry-point.md b/.changeset/all-umd-entry-point.md deleted file mode 100644 index a259b739e5..0000000000 --- a/.changeset/all-umd-entry-point.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -'@lg-chat/leafygreen-chat-provider': patch -'@leafygreen-ui/leafygreen-provider': patch -'@leafygreen-ui/confirmation-modal': patch -'@leafygreen-ui/gallery-indicator': patch -'@leafygreen-ui/inline-definition': patch -'@leafygreen-ui/loading-indicator': patch -'@leafygreen-ui/segmented-control': patch -'@lg-tools/storybook-decorators': patch -'@leafygreen-ui/expandable-card': patch -'@leafygreen-ui/marketing-modal': patch -'@leafygreen-ui/radio-box-group': patch -'@leafygreen-ui/skeleton-loader': patch -'@leafygreen-ui/password-input': patch -'@lg-charts/series-provider': patch -'@lg-chat/fixed-chat-window': patch -'@leafygreen-ui/info-sprinkle': patch -'@lg-chat/message-feedback': patch -'@leafygreen-ui/input-option': patch -'@leafygreen-ui/number-input': patch -'@leafygreen-ui/ordered-list': patch -'@leafygreen-ui/search-input': patch -'@leafygreen-ui/split-button': patch -'@lg-tools/storybook-addon': patch -'@lg-tools/storybook-utils': patch -'@lg-charts/drag-provider': patch -'@lg-chat/chat-disclaimer': patch -'@lg-chat/message-prompts': patch -'@leafygreen-ui/date-picker': patch -'@leafygreen-ui/descendants': patch -'@leafygreen-ui/empty-state': patch -'@leafygreen-ui/form-footer': patch -'@leafygreen-ui/icon-button': patch -'@leafygreen-ui/polymorphic': patch -'@leafygreen-ui/radio-group': patch -'@leafygreen-ui/testing-lib': patch -'@lg-tools/test-harnesses': patch -'@lg-chat/message-rating': patch -'@leafygreen-ui/date-utils': patch -'@leafygreen-ui/form-field': patch -'@leafygreen-ui/pagination': patch -'@leafygreen-ui/text-input': patch -'@leafygreen-ui/typography': patch -'@leafygreen-ui/guide-cue': patch -'@leafygreen-ui/text-area': patch -'@lg-charts/chart-card': patch -'@lg-chat/message-feed': patch -'@leafygreen-ui/checkbox': patch -'@leafygreen-ui/combobox': patch -'@leafygreen-ui/copyable': patch -'@leafygreen-ui/pipeline': patch -'@leafygreen-ui/side-nav': patch -'@lg-chat/chat-window': patch -'@lg-chat/lg-markdown': patch -'@leafygreen-ui/callout': patch -'@leafygreen-ui/emotion': patch -'@leafygreen-ui/palette': patch -'@leafygreen-ui/popover': patch -'@leafygreen-ui/stepper': patch -'@leafygreen-ui/tooltip': patch -'@lg-chat/rich-links': patch -'@leafygreen-ui/avatar': patch -'@leafygreen-ui/banner': patch -'@leafygreen-ui/button': patch -'@leafygreen-ui/drawer': patch -'@leafygreen-ui/portal': patch -'@leafygreen-ui/ripple': patch -'@leafygreen-ui/select': patch -'@leafygreen-ui/toggle': patch -'@leafygreen-ui/tokens': patch -'@lg-chat/input-bar': patch -'@lg-chat/title-bar': patch -'@leafygreen-ui/badge': patch -'@leafygreen-ui/hooks': patch -'@leafygreen-ui/modal': patch -'@leafygreen-ui/table': patch -'@leafygreen-ui/toast': patch -'@lg-tools/codemods': patch -'@lg-tools/slackbot': patch -'@lg-tools/validate': patch -'@lg-charts/colors': patch -'@lg-charts/legend': patch -'@leafygreen-ui/a11y': patch -'@leafygreen-ui/card': patch -'@leafygreen-ui/chip': patch -'@leafygreen-ui/code': patch -'@leafygreen-ui/icon': patch -'@leafygreen-ui/logo': patch -'@leafygreen-ui/menu': patch -'@leafygreen-ui/tabs': patch -'@lg-tools/install': patch -'@lg-chat/message': patch -'@leafygreen-ui/box': patch -'@leafygreen-ui/lib': patch -'@lg-tools/create': patch -'@lg-tools/update': patch -'@lg-charts/core': patch -'@lg-chat/avatar': patch -'@lg-tools/build': patch -'@lg-tools/link': patch -'@lg-tools/lint': patch -'@lg-tools/meta': patch -'@lg-tools/test': patch -'@lg-tools/cli': patch ---- - -Updates `main` entry point in package.json to `./dist/umd` diff --git a/.changeset/bin-umd-dir.md b/.changeset/bin-umd-dir.md deleted file mode 100644 index efaa264b94..0000000000 --- a/.changeset/bin-umd-dir.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@lg-tools/build': patch -'@lg-tools/cli': patch -'@lg-tools/link': patch -'@lg-tools/slackbot': patch ---- - -Updates `./bin` require reference to new UMD build directory diff --git a/.changeset/build-rollup-config.md b/.changeset/build-rollup-config.md deleted file mode 100644 index 3f2188afae..0000000000 --- a/.changeset/build-rollup-config.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@lg-tools/build': minor ---- - -- Only adds output `globals` for UMD builds -- Splits `/testing` entry point if `src/testing/index.ts` file exists diff --git a/.changeset/build-rollup-umd.md b/.changeset/build-rollup-umd.md deleted file mode 100644 index 047c2f8a17..0000000000 --- a/.changeset/build-rollup-umd.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/build': minor ---- - -Updates rollup config to build UMD bundles into `./dist/umd` diff --git a/.changeset/build-sh.md b/.changeset/build-sh.md new file mode 100644 index 0000000000..6f3ed4eedb --- /dev/null +++ b/.changeset/build-sh.md @@ -0,0 +1,5 @@ +--- +'@lg-tools/build': patch +--- + +Updates build scripts to run with `sh` diff --git a/.changeset/build-tsconfig-bundler.md b/.changeset/build-tsconfig-bundler.md deleted file mode 100644 index 90a2a906a9..0000000000 --- a/.changeset/build-tsconfig-bundler.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/build': minor ---- - -Updates `package.tsconfig.json` "moduleResolution" to "bundler", and "target" to "ES2020" diff --git a/.changeset/build-tsconfig-configDir.md b/.changeset/build-tsconfig-configDir.md deleted file mode 100644 index fa7ca7da5f..0000000000 --- a/.changeset/build-tsconfig-configDir.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@lg-tools/build': minor ---- - -- Updates default types directory to `./dist/types` -- Uses "${configDir}" in base package.json baseUrl, rootDir, outDir, & declarationDir properties diff --git a/.changeset/build-typescript-5.md b/.changeset/build-typescript-5.md deleted file mode 100644 index 2d701c7d5b..0000000000 --- a/.changeset/build-typescript-5.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@lg-tools/build': minor ---- - -- Upgrades to TS 5.8. -- Adds `--downlevel` option for `build-ts`. This option exports downleveled `*.d.ts` files for a defined set of targets. -Updates a package's `package.json` if necessary `--update` flag is provided. -This uses [downlevel-dts](https://github.com/sandersn/downlevel-dts) under the hood. diff --git a/.changeset/cli-ts-downlevel.md b/.changeset/cli-ts-downlevel.md deleted file mode 100644 index 7e6ea17146..0000000000 --- a/.changeset/cli-ts-downlevel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/cli': minor ---- - -Adds `--downlevel` option for `build-ts`. This option reads a package's package.json and exports downleveled `*.d.ts` files for all targets listed in `"typeVersions"` diff --git a/.changeset/cli-ts-update-flag.md b/.changeset/cli-ts-update-flag.md deleted file mode 100644 index 71c4a515ca..0000000000 --- a/.changeset/cli-ts-update-flag.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/cli': patch ---- - -Adds `--update` flag for build-ts diff --git a/.changeset/code-postinstall-hljs.md b/.changeset/code-postinstall-hljs.md deleted file mode 100644 index d2cd7cd27b..0000000000 --- a/.changeset/code-postinstall-hljs.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@leafygreen-ui/code': minor ---- - -Adds postinstall script to ensure dependency types are resolved correctly diff --git a/.changeset/few-bulldogs-jump.md b/.changeset/few-bulldogs-jump.md deleted file mode 100644 index faa7906f20..0000000000 --- a/.changeset/few-bulldogs-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@leafygreen-ui/icon': patch ---- - -Updates icon rollup config to add umd bundle to `dist` _and_ `dist/umd` (to avoid breaking the existing entry points) diff --git a/.changeset/grumpy-onions-return.md b/.changeset/grumpy-onions-return.md deleted file mode 100644 index 0ab464e98c..0000000000 --- a/.changeset/grumpy-onions-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@leafygreen-ui/testing-lib': patch ---- - -Updates rollup config for `renderHookServer` diff --git a/.changeset/lg-build-cli.md b/.changeset/lg-build-cli.md deleted file mode 100644 index 1ea9720ff5..0000000000 --- a/.changeset/lg-build-cli.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@lg-tools/build': patch ---- - -Adds `lg-build` cli command. -Usage: -```bash -# Build the production bundle -lg-build bundle - -# Build types -lg-build tsc - -# Builds docs -lg-build docs - -# Build & downlevel types -lg-build tsc --downlevel - -# Build, downlevel & update package.json types references -lg-build tsc --downlevel --update -``` diff --git a/.changeset/lint-update-ts.md b/.changeset/lint-update-ts.md deleted file mode 100644 index 0f79543b0c..0000000000 --- a/.changeset/lint-update-ts.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/lint': patch ---- - -Updates `typescript` peerDepedency to v5.8 diff --git a/.changeset/olive-ways-repeat.md b/.changeset/olive-ways-repeat.md deleted file mode 100644 index 1b8296dc27..0000000000 --- a/.changeset/olive-ways-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@lg-tools/build': patch ---- - -Removes direct build warning. Using `lg-build` directly is now the preferred approach diff --git a/.changeset/palette-bundle-less.md b/.changeset/palette-bundle-less.md deleted file mode 100644 index f2135d4edb..0000000000 --- a/.changeset/palette-bundle-less.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@leafygreen-ui/palette': patch ---- - -Creates local Rollup config to bundle `.less` files diff --git a/.changeset/scrollbar-tokens.md b/.changeset/scrollbar-tokens.md new file mode 100644 index 0000000000..eef19bc332 --- /dev/null +++ b/.changeset/scrollbar-tokens.md @@ -0,0 +1,39 @@ +--- +'@leafygreen-ui/tokens': minor +--- + +Creates scrollbar color tokens and `addScrollbarStyles` + + +#### `scrollbarColor` +Use the `scrollbar-color` CSS property to set the colors of the scrollbar thumb and track. +For Safari, use the `-webkit-scrollbar-thumb` and `-webkit-scrollbar-track` pseudo-elements. + +Usage: + +```tsx +import { scrollbarColor } from '@leafygreen-ui/tokens' + +css` + scrollbar-color: ${scrollbarColor[theme].thumb.primary.default} ${scrollbarColor[theme].track.primary.default}; + &::-webkit-scrollbar-thumb { + background-color: ${scrollbarColor[theme].thumb.primary.default}; + } + &::-webkit-scrollbar-track { + background-color: ${scrollbarColor[theme].track.primary.default}; + } +` +``` + +#### `addScrollbarStyles` + +A utility for quickly adding the above styles for a particular theme & variant. + +```tsx +import { addScrollbarStyles } from '@leafygreen-ui/tokens' + +css` + ${addScrollbarStyles({theme, variant})}; +` + +``` \ No newline at end of file diff --git a/.changeset/testing-entry-points.md b/.changeset/testing-entry-points.md deleted file mode 100644 index e303d27b82..0000000000 --- a/.changeset/testing-entry-points.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -'@leafygreen-ui/code': major -'@leafygreen-ui/gallery-indicator': major -'@leafygreen-ui/select': major -'@leafygreen-ui/table': major -'@leafygreen-ui/tabs': major -'@leafygreen-ui/text-area': major -'@leafygreen-ui/text-input': major -'@leafygreen-ui/toggle': major ---- -Adds code splitting for test utilities -- Adds `/testing` entry point -- Removes `getTestUtils` from main bundle entry point - -When using the component, testing utilities won't be included into your final bundle -```tsx -// App.tsx -import { Component } from `@leafygreen-ui/` -``` - -Testing utilities (and their dependencies) will only be imported if you import them explicitly -```tsx -import { getTestUtils } from `@leafygreen-ui//testing` -``` diff --git a/.changeset/todo-charts.md b/.changeset/todo-charts.md new file mode 100644 index 0000000000..44764c265f --- /dev/null +++ b/.changeset/todo-charts.md @@ -0,0 +1,10 @@ +--- +'@lg-charts/core': patch +--- + +Updates axis `formatter` prop signature to match echarts. +```ts +{ + formatter?: (value: number, index?: number) => string | string; +} +``` diff --git a/.changeset/todo-polymorphic.md b/.changeset/todo-polymorphic.md new file mode 100644 index 0000000000..6e8b82f1c1 --- /dev/null +++ b/.changeset/todo-polymorphic.md @@ -0,0 +1,5 @@ +--- +'@leafygreen-ui/polymorphic': patch +--- + +Replace `ReactElement` with `ReactNode` in type definitions diff --git a/.changeset/typescript-5-all.md b/.changeset/typescript-5-all.md deleted file mode 100644 index 0c2b1367f1..0000000000 --- a/.changeset/typescript-5-all.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -'@leafygreen-ui/a11y': major -'@leafygreen-ui/avatar': major -'@leafygreen-ui/badge': major -'@leafygreen-ui/banner': major -'@leafygreen-ui/box': major -'@leafygreen-ui/button': major -'@leafygreen-ui/callout': major -'@leafygreen-ui/card': major -'@leafygreen-ui/checkbox': major -'@leafygreen-ui/chip': major -'@leafygreen-ui/code': major -'@leafygreen-ui/combobox': major -'@leafygreen-ui/confirmation-modal': major -'@leafygreen-ui/copyable': major -'@leafygreen-ui/date-picker': major -'@leafygreen-ui/descendants': major -'@leafygreen-ui/drawer': major -'@leafygreen-ui/emotion': major -'@leafygreen-ui/empty-state': major -'@leafygreen-ui/expandable-card': major -'@leafygreen-ui/form-field': major -'@leafygreen-ui/form-footer': major -'@leafygreen-ui/gallery-indicator': major -'@leafygreen-ui/guide-cue': major -'@leafygreen-ui/hooks': major -'@leafygreen-ui/icon': major -'@leafygreen-ui/icon-button': major -'@leafygreen-ui/info-sprinkle': major -'@leafygreen-ui/inline-definition': major -'@leafygreen-ui/input-option': major -'@leafygreen-ui/leafygreen-provider': major -'@leafygreen-ui/lib': major -'@leafygreen-ui/loading-indicator': major -'@leafygreen-ui/logo': major -'@leafygreen-ui/marketing-modal': major -'@leafygreen-ui/menu': major -'@leafygreen-ui/modal': major -'@leafygreen-ui/number-input': major -'@leafygreen-ui/ordered-list': major -'@leafygreen-ui/pagination': major -'@leafygreen-ui/palette': major -'@leafygreen-ui/password-input': major -'@leafygreen-ui/pipeline': major -'@leafygreen-ui/polymorphic': major -'@leafygreen-ui/popover': major -'@leafygreen-ui/portal': major -'@leafygreen-ui/radio-box-group': major -'@leafygreen-ui/radio-group': major -'@leafygreen-ui/ripple': major -'@leafygreen-ui/search-input': major -'@leafygreen-ui/segmented-control': major -'@leafygreen-ui/select': major -'@leafygreen-ui/side-nav': major -'@leafygreen-ui/skeleton-loader': major -'@leafygreen-ui/split-button': major -'@leafygreen-ui/stepper': major -'@leafygreen-ui/table': major -'@leafygreen-ui/tabs': major -'@leafygreen-ui/text-area': major -'@leafygreen-ui/text-input': major -'@leafygreen-ui/toast': major -'@leafygreen-ui/toggle': major -'@leafygreen-ui/tokens': major -'@leafygreen-ui/tooltip': major -'@leafygreen-ui/typography': major -'@lg-chat/avatar': major -'@lg-chat/chat-disclaimer': major -'@lg-chat/chat-window': major -'@lg-chat/fixed-chat-window': major -'@lg-chat/input-bar': major -'@lg-chat/leafygreen-chat-provider': major -'@lg-chat/lg-markdown': major -'@lg-chat/message': major -'@lg-chat/message-feed': major -'@lg-chat/message-feedback': major -'@lg-chat/message-prompts': major -'@lg-chat/message-rating': major -'@lg-chat/rich-links': major -'@lg-chat/title-bar': major -'@lg-tools/lint': major - -'@lg-tools/build': minor -'@lg-tools/cli': minor -'@lg-tools/meta': minor -'@lg-tools/codemods': minor -'@leafygreen-ui/date-utils': minor -'@leafygreen-ui/testing-lib': minor -'@lg-tools/storybook-addon': minor -'@lg-tools/storybook-decorators': minor -'@lg-tools/storybook-utils': minor -'@lg-tools/test-harnesses': minor -'@lg-charts/chart-card': minor -'@lg-charts/colors': minor -'@lg-charts/core': minor -'@lg-charts/drag-provider': minor -'@lg-charts/legend': minor -'@lg-charts/series-provider': minor - ---- - -Updates Typescript build to TS5.8 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..d9d8d51390 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules +**/node_modules + +dist +**/dist + +.turbo +**/.turbo + +.git +.storybook +.github \ No newline at end of file diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000000..c134da116b --- /dev/null +++ b/.drone.yml @@ -0,0 +1,83 @@ +--- +kind: pipeline +type: kubernetes +name: default +platform: + arch: arm64 + +trigger: + branch: + - main + - integration/chat + - a/kanopy + +steps: + - name: publish-server + image: plugins/kaniko-ecr + settings: + create_repository: true + registry: 795250896452.dkr.ecr.us-east-1.amazonaws.com + repo: ux-foundations/${DRONE_REPO_NAME} + dockerfile: ./apps/chatbot-server/Dockerfile + tags: + - git-${DRONE_COMMIT_SHA:0:7} + - latest + access_key: + from_secret: ecr_access_key + secret_key: + from_secret: ecr_secret_key + when: + event: + - push + + - name: publish-hello + image: plugins/kaniko-ecr + settings: + create_repository: true + registry: 795250896452.dkr.ecr.us-east-1.amazonaws.com + repo: ux-foundations/${DRONE_REPO_NAME} + dockerfile: ./apps/hello-server/Dockerfile + tags: + - git-${DRONE_COMMIT_SHA:0:7} + - latest + access_key: + from_secret: ecr_access_key + secret_key: + from_secret: ecr_secret_key + when: + event: + - push + + - name: deploy-staging + image: public.ecr.aws/kanopy/drone-helm:v3 + settings: + chart: mongodb/web-app + chart_version: 4.25.0 + add_repos: [mongodb=https://10gen.github.io/helm-charts] + namespace: ux-foundations + release: lg-chatbot-server + values: arch=arm64,image.tag=git-${DRONE_COMMIT_SHA:0:7},image.repository=795250896452.dkr.ecr.us-east-1.amazonaws.com/ux-foundations/${DRONE_REPO_NAME},ingress.enabled=true,ingress.hosts[0]=lg-chatbot-server.ux-foundations.staging.corp.mongodb.com,mesh.enabled=true + values_files: ['environments/staging.yaml'] + api_server: https://api.staging.corp.mongodb.com + kubernetes_token: + from_secret: staging_kubernetes_token + when: + event: + - push + + - name: deploy-staging-hello + image: public.ecr.aws/kanopy/drone-helm:v3 + settings: + chart: mongodb/web-app + chart_version: 4.25.0 + add_repos: [mongodb=https://10gen.github.io/helm-charts] + namespace: ux-foundations + release: lg-hello-server + values: arch=arm64,image.tag=git-${DRONE_COMMIT_SHA:0:7},image.repository=795250896452.dkr.ecr.us-east-1.amazonaws.com/ux-foundations/${DRONE_REPO_NAME},ingress.enabled=true,ingress.hosts[0]=lg-hello-server.ux-foundations.staging.corp.mongodb.com,mesh.enabled=true + values_files: ['environments/staging.yaml'] + api_server: https://api.staging.corp.mongodb.com + kubernetes_token: + from_secret: staging_kubernetes_token + when: + event: + - push diff --git a/.vscode/settings.json b/.vscode/settings.json index a5ee68ce65..0c350a82c5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,17 +18,17 @@ "typescript.preferences.importModuleSpecifier": "project-relative", "github.copilot.chat.codeGeneration.instructions": [ { - "file": "node_modules/@lg-tools/prompt-kit/src/prompts/codeGeneration.md" + "file": ".github/copilotInstructions/codeGeneration.md" } ], "github.copilot.chat.commitMessageGeneration.instructions": [ { - "file": "node_modules/@lg-tools/prompt-kit/src/prompts/commitMessageGeneration.md" + "file": ".github/copilotInstructions/commitMessageGeneration.md" } ], "github.copilot.chat.testGeneration.instructions": [ { - "file": "node_modules/@lg-tools/prompt-kit/src/prompts/testGeneration.md" + "file": ".github/copilotInstructions/testGeneration.md" } ] } diff --git a/apps/chatbot-server/.env.example b/apps/chatbot-server/.env.example index d509c9450c..b3eece0917 100644 --- a/apps/chatbot-server/.env.example +++ b/apps/chatbot-server/.env.example @@ -20,4 +20,20 @@ AZURE_OPENAI_API_EMBEDDING_DEPLOYMENT_URL=https://.openai.azure.c AZURE_OPENAI_CHAT_COMPLETION_MODEL=gpt-4.1 AZURE_OPENAI_API_CHAT_COMPLETION_DEPLOYMENT_NAME=gpt-4.1 -AZURE_OPENAI_API_CHAT_COMPLETION_DEPLOYMENT_URL=https://.openai.azure.com/openai/deployments/gpt-4.1/chat/completions?api-version=2025-01-01-preview \ No newline at end of file +AZURE_OPENAI_API_CHAT_COMPLETION_DEPLOYMENT_URL=https://.openai.azure.com/openai/deployments/gpt-4.1/chat/completions?api-version=2025-01-01-preview + +# DEPLOYMENT +NAMESPACE=ux-foundations +ALLOWED_ORIGINS=origin1,origin2,origin3 + + +# Set the KUBECONFIG context +# ``` +# kubectl config use-context api.staging.corp.mongodb.com +# kubectl config set-context --current --namespace=$NAMESPACE +# ``` + +# Run the following command to get the tokens +staging_kubernetes_token=`kubectl get secret kanopy-cicd-token -o jsonpath="{.data.token}" | base64 --decode && echo` +ecr_access_key=`kubectl get secret ecr -o jsonpath="{.data.ecr_access_key}" | base64 --decode && echo` +ecr_secret_key=`kubectl get secret ecr -o jsonpath="{.data.ecr_secret_key}" | base64 --decode && echo` diff --git a/apps/chatbot-server/Dockerfile b/apps/chatbot-server/Dockerfile new file mode 100644 index 0000000000..765fe912b9 --- /dev/null +++ b/apps/chatbot-server/Dockerfile @@ -0,0 +1,43 @@ +# Use Node.js 18 as the base image +FROM node:18-alpine as base +ENV PORT=8080 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable +RUN pnpm add -g turbo@2.0.6 + +WORKDIR /app + +FROM base as setup + COPY . . + RUN turbo prune lg-chatbot-server --docker + +FROM base as build + RUN apk add --update --no-cache py3-pip make g++ libc6-compat + COPY .npmrc .npmrc + COPY --from=setup /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml + COPY --from=setup /app/out/pnpm-lock.yaml ./pnpm-lock.yaml + COPY --from=setup /app/out/json/ . + + RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile + # Docker runs pnpm as root and then pnpm won't run package scripts unless we pass unsafe-perm + RUN pnpm rebuild --filter="lg-chatbot-server" + + COPY --from=setup /app/out/full/ ./ + COPY turbo.json turbo.json + + # Ensure .bin is in the PATH (lg-build) + RUN pnpm install -w --prefer-offline --unsafe-perm + ENV PATH="/app/node_modules/.bin:/app/tools/build/node_modules/.bin:${PATH}" + + # Build the server app project + RUN pnpm run build --filter="lg-chatbot-server" + + # Set the working directory to the chatbot-server + WORKDIR ./apps/chatbot-server + + EXPOSE $PORT + + # Start the server + CMD ["pnpm", "start"] \ No newline at end of file diff --git a/apps/chatbot-server/package.json b/apps/chatbot-server/package.json index 74065a5e09..df753d06a9 100644 --- a/apps/chatbot-server/package.json +++ b/apps/chatbot-server/package.json @@ -9,10 +9,17 @@ "access": "restricted" }, "scripts": { - "build": "lg build-package", - "tsc": "lg build-ts", + "build": "lg-build bundle", + "tsc": "lg-build tsc", "ingest": "pnpm build && ingest all --config ./dist/esm/ingest.config.js", - "dev": "tsx src/index.ts" + "dev": "tsx src/index.ts", + "start": "node dist/esm/index.js", + "docker:prepare": "pnpm install", + "docker:build": "docker build -t chatbot-server --file ./Dockerfile ../..", + "docker:prune": "docker builder prune --filter \"label=chatbot-server\" -f", + "docker:start": "docker run -p 8080:8080 chatbot-server", + "kanopy:init": "./scripts/init.sh", + "kanopy:forward": "./scripts/fwd.sh" }, "keywords": [], "author": "", @@ -28,6 +35,8 @@ "mongodb-rag-core": "^0.7.0" }, "devDependencies": { + "@lg-tools/build": "workspace:^", + "@rollup/rollup-linux-arm64-musl": "^4.43.0", "mongodb-rag-ingest": "^0.3.1", "nodemon": "^3.0.1", "tsx": "^4.19.4", diff --git a/apps/chatbot-server/rollup.config.mjs b/apps/chatbot-server/rollup.config.mjs index 47dee53f7a..872623150c 100644 --- a/apps/chatbot-server/rollup.config.mjs +++ b/apps/chatbot-server/rollup.config.mjs @@ -1,8 +1,14 @@ -import { esmConfig, umdConfig } from '@lg-tools/build/config/rollup.config.mjs'; +import { esmConfig } from '@lg-tools/build/config/rollup.config.mjs'; const ingestESMConfig = { ...esmConfig, input: './src/ingest/ingest.config.ts', }; -export default [esmConfig, umdConfig, ingestESMConfig]; +export default [ + { + ...esmConfig, + external: [], + }, + ingestESMConfig, +]; diff --git a/apps/chatbot-server/scripts/fwd.sh b/apps/chatbot-server/scripts/fwd.sh new file mode 100755 index 0000000000..cd64161b16 --- /dev/null +++ b/apps/chatbot-server/scripts/fwd.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Script to port-forward to the lg-chatbot-server pod in Kubernetes + +# Source the .env file to get the PORT and NAMESPACE +if [ -f ".env" ]; then + export $(grep -v '^#' ".env" | xargs) +else + echo "Error: .env file not found" + exit 1 +fi + +# Make sure we have a PORT value +if [ -z "$PORT" ]; then + echo "Error: PORT not defined in .env" + exit 1 +fi + +# Set KUBECONFIG path from .env if available +if [ -n "$KUBECONFIG" ]; then + export KUBECONFIG=$KUBECONFIG +fi + +echo "Using KUBECONFIG: $KUBECONFIG" +echo "Looking for latest lg-chatbot-server pod in "$NAMESPACE"..." + +# Get the latest pod starting with lg-chatbot-server +# POD_NAME=$(kubectl get pods -n $NAMESPACE | grep "^lg-chatbot-server" | sort -k1 | tail -n1 | awk '{print $1}') +POD_NAME=$(KUBECONFIG=~/.kube/config.staging kubectl get pods -n $NAMESPACE | grep "^lg-chatbot-server" | sort -k1 | tail -n1 | awk '{print $1}') + +if [ -z "$POD_NAME" ]; then + echo "Error: No pod starting with 'lg-chatbot-server' found" + exit 1 +fi + +echo "Found pod: $POD_NAME" +echo "Setting up port forwarding on port $PORT..." + +# Set up port forwarding +KUBECONFIG=~/.kube/config.staging kubectl port-forward --namespace=$NAMESPACE $POD_NAME 3333:$PORT \ No newline at end of file diff --git a/apps/chatbot-server/scripts/init.sh b/apps/chatbot-server/scripts/init.sh new file mode 100755 index 0000000000..61ad2a7a48 --- /dev/null +++ b/apps/chatbot-server/scripts/init.sh @@ -0,0 +1,19 @@ +echo "Initializing the Kanopy OIDC cluster..." +echo "This script should open your browser to log in to the Kanopy OIDC cluster." +echo "If you cannot authenticate, please follow the instructions here: https://kanopy.corp.mongodb.com/docs/" + +# Source the .env file to get the PORT and NAMESPACE +if [ -f ".env" ]; then + export $(grep -v '^#' ".env" | xargs) +else + echo "Error: .env file not found" + exit 1 +fi + + +CLUSTER=staging +export KUBECONFIG=~/.kube/config.$CLUSTER +mkdir -p $(dirname $KUBECONFIG) +kanopy-oidc kube setup $CLUSTER > $KUBECONFIG +kanopy-oidc kube login +kubectl config set-context $(kubectl config current-context) --namespace=$NAMESPACE diff --git a/apps/chatbot-server/src/index.ts b/apps/chatbot-server/src/index.ts index 360252d2be..e92a9a32c3 100644 --- a/apps/chatbot-server/src/index.ts +++ b/apps/chatbot-server/src/index.ts @@ -23,6 +23,9 @@ Be concise in your answers. // Start the server and clean up resources on SIGINT. const PORT = process.env.PORT || 3030; +const allowedOrigins = process.env.ALLOWED_ORIGINS + ? process.env.ALLOWED_ORIGINS.split(',') + : []; const startServer = async () => { const { @@ -41,6 +44,12 @@ const startServer = async () => { generateUserPrompt, systemPrompt, }, + corsOptions: { + credentials: true, + withCredentials: true, + methods: ['GET', 'POST', 'PUT', 'OPTIONS'], + origin: allowedOrigins, + }, maxRequestTimeoutMs: 30000, }; diff --git a/apps/chatbot-server/src/ingest/utils/webSourceConstructor.ts b/apps/chatbot-server/src/ingest/utils/webSourceConstructor.ts index e9f35eb5cd..26ab0b7819 100644 --- a/apps/chatbot-server/src/ingest/utils/webSourceConstructor.ts +++ b/apps/chatbot-server/src/ingest/utils/webSourceConstructor.ts @@ -1,5 +1,8 @@ /* eslint-disable no-console */ -import { recursiveCrawlFromBaseURL } from '@lg-tools/crawler'; +import { + type CrawlerCallback, + recursiveCrawlFromBaseURL, +} from '@lg-tools/crawler'; import { trimEnd } from 'lodash-es'; import { Page } from 'mongodb-rag-core'; import { type DataSource } from 'mongodb-rag-core/dataSources'; @@ -29,28 +32,27 @@ export async function webSourceConstructor( verbose && console.log(`🐶 Fetching source ${source}`); const pages: Array = []; - await recursiveCrawlFromBaseURL( - ({ document, title, href }) => { - verbose && console.log(`🪲 Crawled page ${title} - ${href}`); - pages.push({ - url: href, - title, - body: document.pageContent, - format: 'txt', - sourceName: source, - metadata: { - id: document.id, - ...document.metadata, - }, - }); - }, - { - baseUrl: source, - maxDepth, - verbose, - enableRecursion: true, - }, - ); + const crawlerCallback: CrawlerCallback = ({ document, title, href }) => { + verbose && console.log(`🪲 Crawled page ${title} - ${href}`); + pages.push({ + url: href, + title, + body: document.pageContent, + format: 'txt', + sourceName: source, + metadata: { + id: document.id, + ...document.metadata, + }, + }); + }; + + await recursiveCrawlFromBaseURL(crawlerCallback, { + baseUrl: source, + maxDepth, + verbose, + enableRecursion: true, + }); return pages; }, diff --git a/apps/chatbot-server/tsconfig.json b/apps/chatbot-server/tsconfig.json index 4eae470f7a..6f76081bf9 100644 --- a/apps/chatbot-server/tsconfig.json +++ b/apps/chatbot-server/tsconfig.json @@ -11,6 +11,8 @@ "include": ["./src/**/*.ts"], "exclude": ["node_modules", "dist"], "references": [ - { "path": "../../tools/crawler" }, + { + "path": "../../tools/crawler" + }, ], } diff --git a/apps/hello-server/Dockerfile b/apps/hello-server/Dockerfile new file mode 100644 index 0000000000..50c0a4b2c9 --- /dev/null +++ b/apps/hello-server/Dockerfile @@ -0,0 +1,43 @@ +# Use Node.js 18 as the base image +FROM node:18-alpine as base +ENV PORT=8080 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable +RUN pnpm add -g turbo@2.0.6 + +WORKDIR /app + +FROM base as setup + COPY . . + RUN turbo prune lg-hello-server --docker + +FROM base as build + RUN apk add --update --no-cache py3-pip make g++ libc6-compat + COPY .npmrc .npmrc + COPY --from=setup /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml + COPY --from=setup /app/out/pnpm-lock.yaml ./pnpm-lock.yaml + COPY --from=setup /app/out/json/ . + + RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \ + pnpm install --frozen-lockfile + # Docker runs pnpm as root and then pnpm won't run package scripts unless we pass unsafe-perm + RUN pnpm rebuild --filter="lg-hello-server" + + COPY --from=setup /app/out/full/ ./ + COPY turbo.json turbo.json + + # Ensure .bin is in the PATH (lg-build) + RUN pnpm install -w --prefer-offline --unsafe-perm + ENV PATH="/app/node_modules/.bin:/app/tools/build/node_modules/.bin:${PATH}" + + # Build the server app project + RUN pnpm run build --filter="lg-hello-server" + + # Set the working directory to the hello-server + WORKDIR ./apps/hello-server + + EXPOSE $PORT + + # Start the server + CMD ["pnpm", "start"] \ No newline at end of file diff --git a/apps/hello-server/index.js b/apps/hello-server/index.js new file mode 100644 index 0000000000..5d089ea237 --- /dev/null +++ b/apps/hello-server/index.js @@ -0,0 +1,21 @@ +const express = require('express'); + +const app = express(); +const port = 8080; + +app.get('/hello', (req, res) => { + res.status(200); + res.setHeader('Content-Type', 'application/json'); + res.setHeader('Access-Control-Allow-Credentials', 'true'); + res.setHeader( + 'Access-Control-Allow-Methods', + 'GET, POST, PUT, DELETE, OPTIONS', + ); + res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000'); + + res.send('Hello, World!'); +}); + +app.listen(port, () => { + console.log(`Server running at http://localhost:${port}`); +}); diff --git a/apps/hello-server/package.json b/apps/hello-server/package.json new file mode 100644 index 0000000000..5716e8138e --- /dev/null +++ b/apps/hello-server/package.json @@ -0,0 +1,17 @@ +{ + "name": "lg-hello-server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node index.js", + "docker:build": "docker build -t hello-server --file ./Dockerfile ../..", + "docker:start": "docker run -p 8080:8080 hello-server" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.18.2" + } +} diff --git a/charts/chart-card/CHANGELOG.md b/charts/chart-card/CHANGELOG.md index 73d0a330c3..890b845626 100644 --- a/charts/chart-card/CHANGELOG.md +++ b/charts/chart-card/CHANGELOG.md @@ -1,5 +1,34 @@ # @lg-charts/chart-card +## 1.0.0 + +### Minor Changes + +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @leafygreen-ui/icon-button@17.0.0 + - @leafygreen-ui/typography@21.0.0 + - @leafygreen-ui/emotion@5.0.0 + - @leafygreen-ui/tokens@3.0.0 + - @leafygreen-ui/hooks@9.0.0 + - @leafygreen-ui/icon@14.0.0 + - @leafygreen-ui/lib@15.0.0 + ## 0.2.5 ### Patch Changes diff --git a/charts/chart-card/package.json b/charts/chart-card/package.json index 1cb152169c..a078299dde 100644 --- a/charts/chart-card/package.json +++ b/charts/chart-card/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/chart-card", - "version": "0.2.5", + "version": "1.0.0", "description": "lg-charts ChartCard", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", diff --git a/charts/colors/CHANGELOG.md b/charts/colors/CHANGELOG.md index b202d10271..96ab6dec6b 100644 --- a/charts/colors/CHANGELOG.md +++ b/charts/colors/CHANGELOG.md @@ -1,5 +1,30 @@ # @lg-charts/colors +## 1.0.0 + +### Minor Changes + +- 21371bddd: Refactor colors into separate `darkColors` and `lightColors` arrays and add `DarkColor` and `LightColor` types +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @leafygreen-ui/palette@5.0.0 + - @leafygreen-ui/lib@15.0.0 + ## 0.2.4 ### Patch Changes diff --git a/charts/colors/package.json b/charts/colors/package.json index 1062800a6b..e2408d0343 100644 --- a/charts/colors/package.json +++ b/charts/colors/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/colors", - "version": "0.2.4", + "version": "1.0.0", "description": "lg-charts colors", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", diff --git a/charts/colors/src/colors.ts b/charts/colors/src/colors.ts index aecb2305cb..6e48b6bc7b 100644 --- a/charts/colors/src/colors.ts +++ b/charts/colors/src/colors.ts @@ -1,40 +1,47 @@ import { Theme } from '@leafygreen-ui/lib'; import { palette } from '@leafygreen-ui/palette'; +// non-palette values used for a11y +export const darkColors = [ + palette.blue.base, + palette.green.dark1, + '#D68000', + palette.red.base, + palette.purple.base, + palette.blue.light1, + palette.green.base, + palette.yellow.base, + palette.red.light1, + palette.purple.light2, + palette.blue.light2, + palette.green.light1, + palette.yellow.light2, + palette.red.light2, + palette.purple.light3, +] as const; +export type DarkColor = (typeof darkColors)[number]; + +// non-palette values used for a11y +export const lightColors = [ + palette.blue.base, + palette.green.dark1, + '#D68000', + palette.red.base, + palette.purple.dark2, + palette.blue.dark1, + palette.green.dark2, + palette.yellow.dark2, + palette.red.dark2, + palette.purple.dark3, + palette.blue.light1, + '#00A982', + '#B08B2E', + '#F86259', + palette.purple.base, +] as const; +export type LightColor = (typeof lightColors)[number]; + export const colors = { - [Theme.Dark]: [ - palette.blue.base, - palette.green.dark1, - '#D68000', - palette.red.base, - palette.purple.base, - palette.blue.light1, - palette.green.base, - palette.yellow.base, - palette.red.light1, - palette.purple.light2, - palette.blue.light2, - palette.green.light1, - palette.yellow.light2, - palette.red.light2, - palette.purple.light3, - ], - // non-palette values used for a11y - [Theme.Light]: [ - palette.blue.base, - palette.green.dark1, - '#D68000', - palette.red.base, - palette.purple.dark2, - palette.blue.dark1, - palette.green.dark2, - palette.yellow.dark2, - palette.red.dark2, - palette.purple.dark3, - palette.blue.light1, - '#00A982', - '#B08B2E', - '#F86259', - palette.purple.base, - ], -}; + [Theme.Dark]: darkColors, + [Theme.Light]: lightColors, +} as const; diff --git a/charts/colors/src/index.ts b/charts/colors/src/index.ts index 3f2f5efc70..33840613cc 100644 --- a/charts/colors/src/index.ts +++ b/charts/colors/src/index.ts @@ -1 +1,7 @@ -export { colors } from './colors'; +export { + colors, + type DarkColor, + darkColors, + type LightColor, + lightColors, +} from './colors'; diff --git a/charts/core/CHANGELOG.md b/charts/core/CHANGELOG.md index 982a25e5d1..92c486cf98 100644 --- a/charts/core/CHANGELOG.md +++ b/charts/core/CHANGELOG.md @@ -1,5 +1,52 @@ # @lg-charts/core +## 1.2.0 + +### Minor Changes + +- 4e7a6b536: [LG-4769](https://jira.mongodb.org/browse/LG-4769): fix label of event marker line bleeding out of canvas + [LG-5145](https://jira.mongodb.org/browse/LG-5145): add dark mode symbols for event markers + +## 1.1.0 + +### Minor Changes + +- 4d350c5fb: [LG-4580](https://jira.mongodb.org/browse/LG-4580): implement tooltip pinning and visibility management + +## 1.0.1 + +### Minor Changes + +- 21371bddd: [LG-5091](https://jira.mongodb.org/browse/LG-5091): add `customColors` prop to `SeriesProvider` to enable customizing chart component colors +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [21371bddd] +- Updated dependencies [21371bddd] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @lg-charts/series-provider@1.0.0 + - @leafygreen-ui/typography@21.0.0 + - @lg-charts/chart-card@1.0.0 + - @leafygreen-ui/emotion@5.0.0 + - @leafygreen-ui/palette@5.0.0 + - @leafygreen-ui/tokens@3.0.0 + - @leafygreen-ui/hooks@9.0.0 + - @lg-charts/colors@1.0.0 + - @leafygreen-ui/lib@15.0.0 + ## 0.18.0 ### Minor Changes diff --git a/charts/core/package.json b/charts/core/package.json index 09fce92a49..0339590d3d 100644 --- a/charts/core/package.json +++ b/charts/core/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/core", - "version": "0.18.0", + "version": "1.2.0", "description": "lg-charts Core Chart Components", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", @@ -19,6 +19,8 @@ "@dnd-kit/utilities": "^3.2.2", "@leafygreen-ui/emotion": "workspace:^", "@leafygreen-ui/hooks": "workspace:^", + "@leafygreen-ui/icon": "workspace:^", + "@leafygreen-ui/icon-button": "workspace:^", "@leafygreen-ui/lib": "workspace:^", "@leafygreen-ui/palette": "workspace:^", "@leafygreen-ui/tokens": "workspace:^", @@ -34,9 +36,7 @@ }, "devDependencies": { "@faker-js/faker": "8.0.2", - "@leafygreen-ui/icon": "workspace:^", - "@lg-tools/build": "workspace:^", - "@types/lodash.debounce": "^4.0.9" + "@lg-tools/build": "workspace:^" }, "repository": { "type": "git", diff --git a/charts/core/src/Chart.stories.tsx b/charts/core/src/Chart.stories.tsx index 095f43fa0c..77aa231e15 100644 --- a/charts/core/src/Chart.stories.tsx +++ b/charts/core/src/Chart.stories.tsx @@ -1072,7 +1072,7 @@ export const WithWarningEventMarkerLine: StoryObj<{}> = { }, }; -export const WithZoomAndTooltip: StoryObj<{}> = { +export const WithZoom: StoryObj<{}> = { render: () => { return ( = { }, }; -export const WithZoom: StoryObj<{}> = { +export const WithXAxisZoom: StoryObj<{}> = { render: () => { return ( {lineData.map(({ name, data }) => ( @@ -1106,12 +1105,12 @@ export const WithZoom: StoryObj<{}> = { }, }; -export const WithXAxisZoom: StoryObj<{}> = { +export const WithYAxisZoom: StoryObj<{}> = { render: () => { return ( {lineData.map(({ name, data }) => ( @@ -1122,20 +1121,27 @@ export const WithXAxisZoom: StoryObj<{}> = { }, }; -export const WithYAxisZoom: StoryObj<{}> = { +export const WithZoomAndTooltip: StoryObj<{}> = { render: () => { return ( + {lineData.map(({ name, data }) => ( ))} ); }, + parameters: { + chromatic: { + disableSnapshot: true, + }, + }, }; export const SyncedByGroupID: StoryObj<{}> = { diff --git a/charts/core/src/Chart/Chart.tsx b/charts/core/src/Chart/Chart.tsx index 9701aa2362..38b1ba146e 100644 --- a/charts/core/src/Chart/Chart.tsx +++ b/charts/core/src/Chart/Chart.tsx @@ -38,6 +38,7 @@ export function Chart({ className, state = ChartStates.Unset, dragId = '', + id: idProp, ...rest }: ChartProps) { const { theme } = useDarkMode(darkModeProp); @@ -46,6 +47,7 @@ export function Chart({ onChartReady, zoomSelect, onZoomSelect, + chartId: idProp, groupId, state, }); @@ -102,6 +104,7 @@ export function Chart({ ref={chart.ref} className={chartStyles} data-testid="lg-charts-core-chart-echart" + id={chart.id} {...rest} /> diff --git a/charts/core/src/Chart/config/getDefaultChartOptions.ts b/charts/core/src/Chart/config/getDefaultChartOptions.ts index 94fe754ac8..fd85577c21 100644 --- a/charts/core/src/Chart/config/getDefaultChartOptions.ts +++ b/charts/core/src/Chart/config/getDefaultChartOptions.ts @@ -9,6 +9,7 @@ import { Variant, } from '@leafygreen-ui/tokens'; +import { DEFAULT_TOOLTIP_OPTIONS } from '../../constants'; import { ChartOptions } from '../Chart.types'; const commonAxisOptions = { @@ -92,13 +93,5 @@ export const getDefaultChartOptions = ( }, }, - // Adds vertical dashed line on hover, even when no tooltip is shown - tooltip: { - axisPointer: { - z: 0, // Prevents dashed emphasis line from being rendered on top of mark lines and labels - }, - show: true, - trigger: 'axis', - formatter: () => '', - }, + ...DEFAULT_TOOLTIP_OPTIONS, }); diff --git a/charts/core/src/Chart/hooks/useChart.spec.ts b/charts/core/src/Chart/hooks/useChart.spec.ts index d7e3231305..8683359050 100644 --- a/charts/core/src/Chart/hooks/useChart.spec.ts +++ b/charts/core/src/Chart/hooks/useChart.spec.ts @@ -105,7 +105,9 @@ describe('@lg-echarts/core/hooks/useChart', () => { // Simulate zoom select event const zoomEventResponse = { start: 0, end: 100 }; - const zoomSelectHandler = on.mock.calls[0][1]; + const zoomSelectHandler = on.mock.calls.find( + ([action, _]) => action === EChartEventsMock.ZoomSelect, + )[1]; act(() => { zoomSelectHandler(zoomEventResponse); }); @@ -125,11 +127,18 @@ describe('@lg-echarts/core/hooks/useChart', () => { (useEchart as jest.Mock).mockReturnValue(mockEchartInstance); - const { result } = renderHook(() => useChart({ theme: 'dark' })); + const { result } = renderHook(() => + useChart({ chartId: 'test-chart-id', theme: 'dark' }), + ); expect(result.current).toEqual({ ...mockEchartInstance, + id: 'test-chart-id', + isChartHovered: true, ref: expect.any(Function), + setTooltipMounted: expect.any(Function), + state: undefined, + tooltipPinned: false, }); }); diff --git a/charts/core/src/Chart/hooks/useChart.ts b/charts/core/src/Chart/hooks/useChart.ts index 11cb8fb75c..11abaeb568 100644 --- a/charts/core/src/Chart/hooks/useChart.ts +++ b/charts/core/src/Chart/hooks/useChart.ts @@ -1,15 +1,19 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useIdAllocator } from '@leafygreen-ui/hooks'; + import { useEchart } from '../../Echart'; import { EChartEvents } from '../../Echart'; import { getDefaultChartOptions } from '../config'; import type { ChartHookProps, ChartInstance } from './useChart.types'; +import { useTooltipVisibility } from './useTooltipVisibility'; export function useChart({ onChartReady = () => {}, zoomSelect, onZoomSelect, + chartId, groupId, theme, state, @@ -24,6 +28,8 @@ export function useChart({ */ const [container, setContainer] = useState(null); + const id = useIdAllocator({ id: chartId, prefix: 'lg-chart' }); + const echart = useEchart({ container, initialOptions, @@ -33,7 +39,6 @@ export function useChart({ const { addToGroup, enableZoom, - hideTooltip, off, on, ready, @@ -49,8 +54,16 @@ export function useChart({ onChartReady(); }, [ready, onChartReady]); + const { isChartHovered, setTooltipMounted, tooltipPinned } = + useTooltipVisibility({ + chartId: id, + container, + echart, + groupId, + }); + useEffect(() => { - if (!ready || !groupId) { + if (!ready || !groupId || tooltipPinned) { return; } @@ -59,7 +72,7 @@ export function useChart({ return () => { removeFromGroup(); }; - }, [ready, groupId, addToGroup, removeFromGroup]); + }, [ready, groupId, addToGroup, removeFromGroup, tooltipPinned]); // SETUP AND ENABLE ZOOM useEffect(() => { @@ -96,27 +109,6 @@ export function useChart({ }); }, [ready, onZoomSelect, on]); - // We want to hide the tooltip when it's hovered over any `EventMarkerPoint` - useEffect(() => { - if (!ready) { - return; - } - - on('mouseover', e => { - if (e.componentType === 'markPoint') { - hideTooltip(); - on('mousemove', hideTooltip); - } - }); - - // Stop hiding once the mouse leaves the `EventMarkerPoint` - on('mouseout', e => { - if (e.componentType === 'markPoint') { - off('mousemove', hideTooltip); - } - }); - }, [echart, hideTooltip, off, on, ready]); - const initialRenderRef = useRef(true); const handleResize = useCallback(() => { @@ -170,7 +162,11 @@ export function useChart({ return { ...echart, + id, + isChartHovered, ref: setContainer, + setTooltipMounted, state, + tooltipPinned, }; } diff --git a/charts/core/src/Chart/hooks/useChart.types.ts b/charts/core/src/Chart/hooks/useChart.types.ts index 2808f67d2e..58678e00df 100644 --- a/charts/core/src/Chart/hooks/useChart.types.ts +++ b/charts/core/src/Chart/hooks/useChart.types.ts @@ -5,6 +5,8 @@ import { Theme } from '@leafygreen-ui/lib'; import type { EChartsInstance, EChartZoomSelectionEvent } from '../../Echart'; import { ChartStates } from '../Chart.types'; +import { UseTooltipVisibilityReturnObj } from './useTooltipVisibility.types'; + export type ZoomSelect = | { xAxis: boolean; @@ -19,6 +21,11 @@ export type ZoomSelect = export interface ChartHookProps { theme: Theme; + /** + * The id of the chart. + */ + chartId?: string; + /** * Charts with the same `groupId` will have their tooltips synced across charts. */ @@ -47,6 +54,8 @@ export interface ChartHookProps { export interface ChartInstance extends EChartsInstance, - Pick { + Pick, + UseTooltipVisibilityReturnObj { + id: string; ref: RefCallback; } diff --git a/charts/core/src/Chart/hooks/useTooltipVisibility.ts b/charts/core/src/Chart/hooks/useTooltipVisibility.ts new file mode 100644 index 0000000000..de5a99f75f --- /dev/null +++ b/charts/core/src/Chart/hooks/useTooltipVisibility.ts @@ -0,0 +1,307 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; + +import { CHART_TOOLTIP_CLASSNAME } from '../../constants'; +import { EChartEvents, EChartsInstance } from '../../Echart'; + +import { UseTooltipVisibilityReturnObj } from './useTooltipVisibility.types'; + +/** + * Hook to manage the visibility of the tooltip in the chart including pinning behavior. + */ +export const useTooltipVisibility = ({ + chartId, + container, + echart, + groupId, +}: { + chartId: string; + container: HTMLDivElement | null; + echart: EChartsInstance; + groupId?: string; +}): UseTooltipVisibilityReturnObj => { + // if groupId is not provided, this state will always be true + const [isChartHovered, setIsChartHovered] = useState(!groupId); + const [pinnedPosition, setPinnedPosition] = useState([0, 0]); + const [tooltipMounted, setTooltipMounted] = useState(false); + const [tooltipPinned, setTooltipPinned] = useState(false); + + const tooltipMountedRef = useRef(tooltipMounted); + const tooltipPinnedRef = useRef(tooltipPinned); + + const { + addToGroup, + hideTooltip, + off, + on, + ready, + removeFromGroup, + showTooltip, + } = echart; + + /** + * Event listener callback added to the chart that is called on `mouseenter` + * or `mouseleave` to set the `isChartHovered` state. + */ + const toggleChartHover = useCallback((isMouseEnter: boolean) => { + setIsChartHovered(isMouseEnter); + }, []); + + /** + * Event listener callback added to the chart that is called on mouse move + * to show the tooltip. + */ + const showTooltipOnMouseMove = useCallback( + (params: any) => { + if (!tooltipMountedRef.current || tooltipPinnedRef.current) { + return; + } + + const { offsetX, offsetY } = params; + showTooltip(offsetX, offsetY); + }, + [showTooltip], + ); + + /** + * Event listener callback added to the close button in the tooltip. When called, + * it hides the tooltip and sets the `tooltipPinned` state to false. + */ + const unpinTooltip = useCallback(() => { + /** + * When the tooltip is pinned, the chart is removed from the group to prevent + * event listeners of sibling charts from triggering the tooltip of current chart. + * + * When unpinning the tooltip, the chart is added back to the group. + */ + if (groupId) { + addToGroup(groupId); + } + + setTooltipPinned(false); + + /** + * Use requestAnimationFrame to ensure that the tooltip is hidden after + * `ChartTooltip` has reacted to the `tooltipPinned` state change. + */ + requestAnimationFrame(() => { + hideTooltip(); + }); + }, [addToGroup, groupId, hideTooltip]); + + /** + * Helper method to add event listener to the close button in the tooltip. + * + * The echarts tooltip `formatter` cannot pass the `onClick` event to the button, + * so it has to be added manually. + */ + const addUnpinCallbackToCloseButton = useCallback(() => { + const btn = document.querySelector(`[data-chartid="${chartId}"]`); + + if (btn instanceof HTMLElement && !btn.dataset.bound) { + btn.addEventListener('click', unpinTooltip); + btn.dataset.bound = 'true'; // prevents duplicate listeners + } + }, [chartId, unpinTooltip]); + + /** + * Event listener callback added to the chart that is called on click to record the + * `pinnedPosition` state and set the `tooltipPinned` state to true. + * + * Separate effect is used to show tooltip and add the unpin event listener because + * the `ChartTooltip` instance must first react to the `tooltipPinned` state change. + */ + const pinTooltipOnClick = useCallback( + (params: any) => { + if (!tooltipMountedRef.current || tooltipPinnedRef.current) { + return; + } + + /** + * When the tooltip is pinned, the chart is removed from the group to prevent + * event listeners of sibling charts from triggering the tooltip of current chart. + */ + if (groupId) { + removeFromGroup(); + } + + /** + * Remove the mouse move and click event listeners to prevent the tooltip from + * moving when it is pinned. User can unpin it by clicking the close button in + * the tooltip which will turn the listeners back on. + */ + off(EChartEvents.MouseMove, showTooltipOnMouseMove, { + useCanvasAsTrigger: true, + }); + off(EChartEvents.Click, pinTooltipOnClick, { useCanvasAsTrigger: true }); + + const { offsetX, offsetY } = params; + setPinnedPosition([offsetX, offsetY]); + setTooltipPinned(true); + }, + [groupId, off, showTooltipOnMouseMove, removeFromGroup], + ); + + /** + * Event listener callback that is called when mousing over a mark point or line. + * It hides the tooltip and disables the chart click event listener. + */ + const hideTooltipOnMouseOverMark = useCallback( + (params: any) => { + if (!tooltipMountedRef.current) { + return; + } + + if ( + params.componentType === 'markPoint' || + params.componentType === 'markLine' + ) { + hideTooltip(); + on(EChartEvents.MouseMove, hideTooltip); + off(EChartEvents.Click, pinTooltipOnClick, { + useCanvasAsTrigger: true, + }); + } + }, + [hideTooltip, off, on, pinTooltipOnClick], + ); + + /** + * Event listener callback that is called when mousing out of a mark point or line. + * It stops hiding the tooltip and re-enables the chart click event listener. + */ + const stopHideTooltipOnMouseOutMark = useCallback( + (params: any) => { + if (!tooltipMountedRef.current) { + return; + } + + if ( + params.componentType === 'markPoint' || + params.componentType === 'markLine' + ) { + off(EChartEvents.MouseMove, hideTooltip); + on(EChartEvents.Click, pinTooltipOnClick, { + useCanvasAsTrigger: true, + }); + } + }, + [hideTooltip, off, on, pinTooltipOnClick], + ); + + useEffect(() => { + tooltipMountedRef.current = tooltipMounted; + }, [tooltipMounted]); + + useEffect(() => { + tooltipPinnedRef.current = tooltipPinned; + }, [tooltipPinned]); + + /** + * Effect to add event listeners to the chart container to toggle the `isChartHovered` + * state on mouse enter and leave when the chart is grouped. + * + * When charts are grouped, the mousemove events are synced across all charts to render + * uniformly aligned axis pointers. `isChartHovered` state is used to determine if the + * tooltip content should also be displayed or not. + */ + useEffect(() => { + if (!container || !groupId) { + return; + } + + container.addEventListener('mouseenter', () => toggleChartHover(true)); + container.addEventListener('mouseleave', () => toggleChartHover(false)); + + return () => { + container.removeEventListener('mouseenter', () => toggleChartHover(true)); + container.removeEventListener('mouseleave', () => + toggleChartHover(false), + ); + }; + }, [container, groupId, toggleChartHover]); + + /** + * Effect to turn on the tooltip event listeners when the chart is ready and tooltip + * is not already pinned. + */ + useEffect(() => { + if (!ready || tooltipPinned) { + return; + } + + on(EChartEvents.MouseMove, showTooltipOnMouseMove, { + useCanvasAsTrigger: true, + }); + on(EChartEvents.Click, pinTooltipOnClick, { + useCanvasAsTrigger: true, + }); + }, [on, pinTooltipOnClick, ready, showTooltipOnMouseMove, tooltipPinned]); + + /** + * Effect to add the event listeners to hide the tooltip when hovering a mark. + */ + useEffect(() => { + if (!ready) { + return; + } + + on(EChartEvents.MouseOver, hideTooltipOnMouseOverMark); + on(EChartEvents.MouseOut, stopHideTooltipOnMouseOutMark); + }, [ + pinTooltipOnClick, + showTooltipOnMouseMove, + hideTooltipOnMouseOverMark, + stopHideTooltipOnMouseOutMark, + hideTooltip, + off, + on, + ready, + tooltipPinned, + ]); + + /** + * Effect to react to the `tooltipPinned` state and show the tooltip. + * + * `setTimeout` is used to defer execution of callbacks to show tooltip and add unpin + * callback until the next tick of the event loop at which point the echarts tooltip + * is rendered and in the DOM + */ + useEffect(() => { + if (!tooltipPinned) { + return; + } + + const [x, y] = pinnedPosition; + setTimeout(() => { + showTooltip(x, y); + addUnpinCallbackToCloseButton(); + }); + }, [ + isChartHovered, + tooltipPinned, + pinnedPosition, + showTooltip, + addUnpinCallbackToCloseButton, + ]); + + /** + * Effect to clean up any tooltip elements when the component is unmounted. + * + * This is specifically required for cases where the echarts instance is cleaned up + * before the `hideTooltip` action can be called on the instance. + */ + useEffect(() => { + return () => { + const tooltipEls = document.getElementsByClassName( + CHART_TOOLTIP_CLASSNAME, + ); + Array.from(tooltipEls).forEach(el => el.remove()); + }; + }, []); + + return { + isChartHovered, + setTooltipMounted, + tooltipPinned, + }; +}; diff --git a/charts/core/src/Chart/hooks/useTooltipVisibility.types.ts b/charts/core/src/Chart/hooks/useTooltipVisibility.types.ts new file mode 100644 index 0000000000..fba9cc44a4 --- /dev/null +++ b/charts/core/src/Chart/hooks/useTooltipVisibility.types.ts @@ -0,0 +1,20 @@ +export interface UseTooltipVisibilityReturnObj { + /** + * Whether the chart is hovered. + * When charts are grouped, the mousemove events are synced across all + * charts to render uniformly aligned axis pointers. This boolean is used + * to determine if the tooltip content should also be displayed or not. + */ + isChartHovered: boolean; + + /** + * React dispatch function toggled to true when the tooltip is mounted + * and false when unmounted. + */ + setTooltipMounted: React.Dispatch>; + + /** + * Whether the tooltip is visible and pinned. + */ + tooltipPinned: boolean; +} diff --git a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.stories.tsx b/charts/core/src/ChartTooltip/ChartTooltip.stories.tsx similarity index 63% rename from charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.stories.tsx rename to charts/core/src/ChartTooltip/ChartTooltip.stories.tsx index 649bd53612..8f94419bdb 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.stories.tsx +++ b/charts/core/src/ChartTooltip/ChartTooltip.stories.tsx @@ -1,21 +1,56 @@ import React from 'react'; import { storybookArgTypes } from '@lg-tools/storybook-utils'; -import type { StoryObj } from '@storybook/react'; +import type { StoryFn, StoryObj } from '@storybook/react'; +import { css } from '@leafygreen-ui/emotion'; import Icon from '@leafygreen-ui/icon'; +import LeafyGreenProvider from '@leafygreen-ui/leafygreen-provider'; -import { CustomTooltip } from './CustomTooltip'; -import { sampleTooltipParams } from './CustomTooltip.testUtils'; -import { CustomTooltipProps } from './CustomTooltip.types'; +import { getRootStylesText } from './ChartTooltip.styles'; +import { + CustomTooltip, + CustomTooltipProps, + sampleTooltipParams, +} from './CustomTooltip'; + +const TooltipRoot = (Story: StoryFn, ctx: any) => { + const rootClassName = css` + ${getRootStylesText(ctx.args.darkMode ? 'dark' : 'light')} + `; + + return ( + +
+ +
+
+ ); +}; export default { title: 'Charts/ChartTooltip', component: CustomTooltip, + decorators: [TooltipRoot], args: { seriesData: sampleTooltipParams, }, argTypes: { + chartId: { + table: { + disable: true, + }, + }, darkMode: storybookArgTypes.darkMode, + headerFormatter: { + table: { + disable: true, + }, + }, + seriesData: { + table: { + disable: true, + }, + }, seriesNameFormatter: { table: { disable: true, @@ -26,12 +61,19 @@ export default { disable: true, }, }, + sort: { + table: { + disable: true, + }, + }, }, parameters: { generate: { combineArgs: { darkMode: [false, true], + tooltipPinned: [false, true], }, + decorator: TooltipRoot, }, }, }; diff --git a/charts/core/src/ChartTooltip/ChartTooltip.styles.ts b/charts/core/src/ChartTooltip/ChartTooltip.styles.ts new file mode 100644 index 0000000000..63575c0cba --- /dev/null +++ b/charts/core/src/ChartTooltip/ChartTooltip.styles.ts @@ -0,0 +1,25 @@ +import { Theme } from '@leafygreen-ui/lib'; +import { + borderRadius, + color, + fontFamilies, + fontWeights, + InteractionState, + Variant, +} from '@leafygreen-ui/tokens'; + +const TOOLTIP_WIDTH = 270; + +export const getRootStylesText = (theme: Theme) => ` + width: ${TOOLTIP_WIDTH}px; + overflow: hidden; + background-color: ${ + color[theme].background[Variant.InversePrimary][InteractionState.Default] + }; + color: ${color[theme].text[Variant.InversePrimary][InteractionState.Default]}; + border-radius: ${borderRadius[150]}px; + font-family: ${fontFamilies.default}; + font-size: 12px; + line-height: 20px; + font-weight: ${fontWeights.regular}; +`; diff --git a/charts/core/src/ChartTooltip/ChartTooltip.tsx b/charts/core/src/ChartTooltip/ChartTooltip.tsx index 803a45f981..639bde6541 100644 --- a/charts/core/src/ChartTooltip/ChartTooltip.tsx +++ b/charts/core/src/ChartTooltip/ChartTooltip.tsx @@ -2,10 +2,11 @@ import React, { useEffect } from 'react'; import { renderToString } from 'react-dom/server'; import { useDarkMode } from '@leafygreen-ui/leafygreen-provider'; -import { color, InteractionState, Variant } from '@leafygreen-ui/tokens'; import { useChartContext } from '../ChartContext'; +import { CHART_TOOLTIP_CLASSNAME, DEFAULT_TOOLTIP_OPTIONS } from '../constants'; +import { getRootStylesText } from './ChartTooltip.styles'; import { CallbackSeriesDataPoint, ChartTooltipProps, @@ -13,33 +14,58 @@ import { import { CustomTooltip } from './CustomTooltip'; export function ChartTooltip({ + headerFormatter, seriesValueFormatter, seriesNameFormatter, sort, }: ChartTooltipProps) { const { - chart: { ready, updateOptions }, + chart: { + id: chartId, + isChartHovered, + ready, + setTooltipMounted, + tooltipPinned, + updateOptions, + }, } = useChartContext(); - const { theme } = useDarkMode(); + const { darkMode, theme } = useDarkMode(); + + useEffect(() => { + setTooltipMounted(true); + + return () => { + setTooltipMounted(false); + }; + }, [setTooltipMounted]); useEffect(() => { if (!ready) return; updateOptions({ tooltip: { - // Still adding background color to prevent peak of color at corners - backgroundColor: - color[theme].background[Variant.InversePrimary][ - InteractionState.Default - ], - borderWidth: 0, - enterable: false, - confine: true, + /* LOGIC PROPERTIES */ + alwaysShowContent: tooltipPinned, appendTo: 'body', + confine: true, + enterable: tooltipPinned, + renderMode: 'html', + showContent: isChartHovered || tooltipPinned, + trigger: 'axis', + triggerOn: 'none', + + /* STYLING PROPERTIES */ + /** + * using `extraCssText` instead of `className` because emotion-defined class + * didn't have high-enough specificity + */ + className: CHART_TOOLTIP_CLASSNAME, + extraCssText: getRootStylesText(theme), + borderWidth: 0, + padding: 0, showDelay: 0, hideDelay: 0, transitionDuration: 0, - padding: 0, /** * Since the formatter trigger is set to 'axis', the seriesData will be * an array of objects. Additionally, it should contain axis related @@ -52,10 +78,14 @@ export function ChartTooltip({ return renderToString( , ); }, @@ -63,23 +93,19 @@ export function ChartTooltip({ }); return () => { - updateOptions({ - tooltip: { - axisPointer: { - z: 0, // Prevents dashed emphasis line from being rendered on top of mark lines and labels - }, - show: true, - trigger: 'axis', - formatter: () => '', - }, - }); + updateOptions({ ...DEFAULT_TOOLTIP_OPTIONS }); }; }, [ + chartId, + darkMode, + headerFormatter, + isChartHovered, ready, seriesNameFormatter, seriesValueFormatter, sort, theme, + tooltipPinned, updateOptions, ]); diff --git a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.spec.tsx b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.spec.tsx index 1b3fad5f33..cc6a66477e 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.spec.tsx +++ b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.spec.tsx @@ -80,7 +80,7 @@ describe('@lg-charts/core/ChartTooltip/CustomTooltip', () => { test('should render properly formatted date', () => { renderCustomTooltip(); const dateElement = screen.getByText( - /\d{4}\/\d{2}\/\d{2}\/\d{2}:\d{2}:\d{2}/, + /^[A-Z][a-z]{2} \d{1,2}, \d{4}, \d{1,2}:\d{2}:\d{2} [AP]M \(UTC\)$/, ); expect(dateElement).toBeInTheDocument(); }); diff --git a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.styles.ts b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.styles.ts index d001bc5317..308cd3ba99 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.styles.ts +++ b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.styles.ts @@ -1,33 +1,32 @@ import { css } from '@leafygreen-ui/emotion'; import { Theme } from '@leafygreen-ui/lib'; import { - borderRadius, color, - fontFamilies, - fontWeights, InteractionState, spacing, Variant, } from '@leafygreen-ui/tokens'; -export const getContainerStyles = (theme: Theme) => css` - width: 261px; - overflow-y: auto; - background: ${color[theme].background[Variant.InversePrimary][ - InteractionState.Default - ]}; - color: ${color[theme].text[Variant.InversePrimary][InteractionState.Default]}; - padding: ${spacing[150]}px; - border-radius: ${borderRadius[150]}px; - font-family: ${fontFamilies.default}; - font-size: 12px; - line-height: 20px; - font-weight: ${fontWeights.regular}; -`; +const CLOSE_BUTTON_SIZE = 16; export const getHeaderStyles = (theme: Theme) => css` color: ${color[theme].text[Variant.InverseSecondary][ InteractionState.Default ]}; margin-bottom: ${spacing[100]}px; + padding: ${spacing[150]}px ${spacing[150]}px 0; + display: flex; + justify-content: space-between; + align-items: center; +`; + +export const closeButtonStyles = css` + height: ${CLOSE_BUTTON_SIZE}px; + width: ${CLOSE_BUTTON_SIZE}px; +`; + +export const pinTooltipNoteStyles = css` + display: flex; + align-items: center; + gap: ${spacing[50]}px; `; diff --git a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.tsx b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.tsx index 0a18dbed45..90f065460d 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.tsx +++ b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.tsx @@ -1,32 +1,44 @@ import React, { ReactNode } from 'react'; +import CursorIcon from '@leafygreen-ui/icon/dist/Cursor'; +import XIcon from '@leafygreen-ui/icon/dist/X'; +import IconButton from '@leafygreen-ui/icon-button'; import { useDarkMode } from '@leafygreen-ui/leafygreen-provider'; -import { getContainerStyles, getHeaderStyles } from './CustomTooltip.styles'; +import { + closeButtonStyles, + getHeaderStyles, + pinTooltipNoteStyles, +} from './CustomTooltip.styles'; import { CustomTooltipProps } from './CustomTooltip.types'; import { SeriesList } from './SeriesList'; function formatDate(dateTimeStamp: number) { const date = new Date(dateTimeStamp); - const formattedYear = date.getFullYear(); - const formattedMonth = String(date.getMonth() + 1).padStart(2, '0'); - const formattedDay = String(date.getDate()).padStart(2, '0'); - const formattedHour = String(date.getHours()).padStart(2, '0'); - const formattedMinute = String(date.getMinutes()).padStart(2, '0'); - const formattedSecond = String(date.getSeconds()).padStart(2, '0'); - const formattedDate = `${formattedYear}/${formattedMonth}/${formattedDay}`; - const formattedTime = `${formattedHour}:${formattedMinute}:${formattedSecond}`; - - return `${formattedDate}/${formattedTime}`; + + return ( + date.toLocaleString('en-US', { + timeZone: 'UTC', + month: 'short', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: '2-digit', + second: '2-digit', + hour12: true, + }) + ' (UTC)' + ); } export function CustomTooltip({ + chartId, + darkMode, + headerFormatter, seriesData, - seriesValueFormatter, seriesNameFormatter, - headerFormatter, + seriesValueFormatter, sort, - darkMode, + tooltipPinned, }: CustomTooltipProps) { const { theme } = useDarkMode(darkMode); @@ -50,14 +62,33 @@ export function CustomTooltip({ } return ( -
-
{axisValueLabel}
+ <> +
+ {axisValueLabel} + {tooltipPinned ? ( + + + + ) : ( +
+ + Click to Pin +
+ )} +
-
+ ); } diff --git a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.types.tsx b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.types.tsx index 8c53f68d8d..88b9e2bf79 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.types.tsx +++ b/charts/core/src/ChartTooltip/CustomTooltip/CustomTooltip.types.tsx @@ -6,9 +6,11 @@ import { } from '../ChartTooltip.types'; export interface CustomTooltipProps extends DarkModeProps { + chartId: string; + headerFormatter?: ChartTooltipProps['headerFormatter']; seriesData: Array; - sort?: ChartTooltipProps['sort']; - seriesValueFormatter?: ChartTooltipProps['seriesValueFormatter']; seriesNameFormatter?: ChartTooltipProps['seriesNameFormatter']; - headerFormatter?: ChartTooltipProps['headerFormatter']; + seriesValueFormatter?: ChartTooltipProps['seriesValueFormatter']; + sort?: ChartTooltipProps['sort']; + tooltipPinned: boolean; } diff --git a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.styles.ts b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.styles.ts index e69de29bb2..5f4ba682ae 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.styles.ts +++ b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.styles.ts @@ -0,0 +1,28 @@ +import { css } from '@leafygreen-ui/emotion'; +import { Theme } from '@leafygreen-ui/lib'; +import { + color, + InteractionState, + spacing, + Variant, +} from '@leafygreen-ui/tokens'; + +const PINNED_SERIES_LIST_MAX_HEIGHT = 102; + +export const getSeriesListStyles = ({ + theme, + tooltipPinned, +}: { + theme: Theme; + tooltipPinned: boolean; +}) => css` + all: unset; + background-color: ${color[theme].background[Variant.InversePrimary][ + InteractionState.Default + ]}; + overflow-y: auto; + max-height: ${tooltipPinned ? `${PINNED_SERIES_LIST_MAX_HEIGHT}px` : 'none'}; + padding: 0 ${spacing[150]}px ${spacing[150]}px; + display: grid; + gap: ${spacing[100]}px; +`; diff --git a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.tsx b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.tsx index e5f83071e3..b112ba811d 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.tsx +++ b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.tsx @@ -4,6 +4,7 @@ import { SeriesName } from '@lg-charts/series-provider'; import { OptionDataValue } from '../../ChartTooltip.types'; import { SeriesListItem } from '../SeriesListItem'; +import { getSeriesListStyles } from './SeriesList.styles'; import { SeriesListProps } from './SeriesList.types'; function descendingCompareFn(valueA: OptionDataValue, valueB: OptionDataValue) { @@ -23,9 +24,11 @@ export function SeriesList({ seriesValueFormatter, seriesNameFormatter, sort, + theme, + tooltipPinned, }: SeriesListProps) { return ( - <> +
    {seriesData .sort((a, b) => { const [nameA, valueA] = a.data; @@ -50,6 +53,6 @@ export function SeriesList({ seriesNameFormatter={seriesNameFormatter} /> ))} - +
); } diff --git a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.types.ts b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.types.ts index 4838719760..7b29ac4172 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.types.ts +++ b/charts/core/src/ChartTooltip/CustomTooltip/SeriesList/SeriesList.types.ts @@ -1,3 +1,5 @@ +import { Theme } from '@leafygreen-ui/lib'; + import { CustomTooltipProps } from '../CustomTooltip.types'; export interface SeriesListProps { @@ -5,4 +7,6 @@ export interface SeriesListProps { seriesValueFormatter?: CustomTooltipProps['seriesValueFormatter']; seriesNameFormatter?: CustomTooltipProps['seriesNameFormatter']; sort: CustomTooltipProps['sort']; + theme: Theme; + tooltipPinned: CustomTooltipProps['tooltipPinned']; } diff --git a/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.styles.ts b/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.styles.ts index 5d3045fc1c..3f0a938882 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.styles.ts +++ b/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.styles.ts @@ -4,7 +4,6 @@ import { fontFamilies, fontWeights, spacing } from '@leafygreen-ui/tokens'; export const containerStyle = css` display: grid; grid-template-columns: 1fr auto; - margin-bottom: ${spacing[100]}px; gap: ${spacing[500]}px; `; diff --git a/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.tsx b/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.tsx index e2e4878e6d..e97c3a976b 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.tsx +++ b/charts/core/src/ChartTooltip/CustomTooltip/SeriesListItem/SeriesListItem.tsx @@ -32,12 +32,12 @@ export const SeriesListItem = ({ } return ( -
+
  • {name}
    {value}
    -
  • + ); }; diff --git a/charts/core/src/ChartTooltip/CustomTooltip/index.ts b/charts/core/src/ChartTooltip/CustomTooltip/index.ts index bfed1fe356..c5b2620a97 100644 --- a/charts/core/src/ChartTooltip/CustomTooltip/index.ts +++ b/charts/core/src/ChartTooltip/CustomTooltip/index.ts @@ -1 +1,3 @@ export { CustomTooltip } from './CustomTooltip'; +export { sampleTooltipParams } from './CustomTooltip.testUtils'; +export type { CustomTooltipProps } from './CustomTooltip.types'; diff --git a/charts/core/src/Echart/Echart.types.ts b/charts/core/src/Echart/Echart.types.ts index 4b2d9d51bf..7ce4128c9a 100644 --- a/charts/core/src/Echart/Echart.types.ts +++ b/charts/core/src/Echart/Echart.types.ts @@ -12,6 +12,10 @@ import type { ComposeOption, EChartsType } from 'echarts/core'; import { Theme } from '@leafygreen-ui/lib'; +// Type not exported by echarts. +// reference: https://github.com/apache/echarts/blob/master/src/coord/axisCommonTypes.ts#L193 +export type AxisLabelValueFormatter = (value: number, index?: number) => string; + type RequiredSeriesProps = 'type' | 'name' | 'data'; export type EChartSeriesOption = Pick & Partial>; @@ -99,10 +103,15 @@ export interface EChartSetupZoomSelectProps { } interface EChartsEventHandlerType { - (event: EChartEventsType, callback: (params: any) => void): void; + ( + event: EChartEventsType, + callback: (params: any) => void, + options?: Partial<{ useCanvasAsTrigger: boolean }>, + ): void; ( event: 'zoomselect', callback: (params: EChartZoomSelectionEvent) => void, + options?: Partial<{ useCanvasAsTrigger: boolean }>, ): void; } @@ -122,6 +131,7 @@ export interface EChartsInstance { removeSeries: (name: string) => void; resize: () => void; setupZoomSelect: (props: EChartSetupZoomSelectProps) => void; + showTooltip: (x: number, y: number) => void; updateOptions: (options: Omit, 'series'>) => void; } diff --git a/charts/core/src/Echart/useEchart.ts b/charts/core/src/Echart/useEchart.ts index d7152e11bf..4e2564959b 100644 --- a/charts/core/src/Echart/useEchart.ts +++ b/charts/core/src/Echart/useEchart.ts @@ -122,11 +122,11 @@ export function useEchart({ */ const isZoomed = params?.start !== 0 || params?.end !== 100; - if (!isZoomed) { + if (!isZoomed || !echartsInstance) { return; } - echartsInstance?.dispatchAction({ + echartsInstance.dispatchAction({ type: 'dataZoom', start: 0, // percentage of starting position end: 100, // percentage of ending position @@ -135,7 +135,12 @@ export function useEchart({ const enableZoom = useCallback(() => { const echartsInstance = echartsInstanceRef.current; - echartsInstance?.dispatchAction({ + + if (!echartsInstance) { + return; + } + + echartsInstance.dispatchAction({ type: 'takeGlobalCursor', key: 'dataZoomSelect', dataZoomSelectActive: true, @@ -144,7 +149,12 @@ export function useEchart({ const disableZoom = useCallback(() => { const echartsInstance = echartsInstanceRef.current; - echartsInstance?.dispatchAction({ + + if (!echartsInstance) { + return; + } + + echartsInstance.dispatchAction({ type: 'takeGlobalCursor', key: 'dataZoomSelect', dataZoomSelectActive: false, @@ -155,6 +165,10 @@ export function useEchart({ ({ xAxis, yAxis }) => { const echartsInstance = echartsInstanceRef.current; + if (!echartsInstance) { + return; + } + // `0` index enables zoom on that index, `'none'` disables zoom on that index const xAxisIndex: number | string = xAxis ? 0 : 'none'; const yAxisIndex: number | string = yAxis ? 0 : 'none'; @@ -170,33 +184,46 @@ export function useEchart({ }, }); - echartsInstance?.off('dataZoom', clearDataZoom); // prevent adding dupes - echartsInstance?.on('dataZoom', clearDataZoom); + echartsInstance.off('dataZoom', clearDataZoom); // prevent adding dupes + echartsInstance.on('dataZoom', clearDataZoom); }, [clearDataZoom, updateOptions], ); - const off: EChartsInstance['off'] = useCallback((action, callback) => { - const echartsInstance = echartsInstanceRef.current; + const off: EChartsInstance['off'] = useCallback( + (action, callback, options) => { + const echartsInstance = echartsInstanceRef.current; - switch (action) { - case EChartEvents.ZoomSelect: { - echartsInstance?.off('datazoom', callback); - // Remove from active handlers - activeHandlers.current.delete(`${action}-${callback.toString()}`); - break; + if (!echartsInstance) { + return; } - default: { - echartsInstance?.off(action, callback); - activeHandlers.current.delete(`${action}-${callback.toString()}`); + switch (action) { + case EChartEvents.ZoomSelect: { + echartsInstance.off('datazoom', callback); + // Remove from active handlers + activeHandlers.current.delete(`${action}-${callback.toString()}`); + break; + } + + default: { + options?.useCanvasAsTrigger + ? echartsInstance.getZr().off(action, callback) + : echartsInstance.off(action, callback); + activeHandlers.current.delete(`${action}-${callback.toString()}`); + } } - } - }, []); + }, + [], + ); - const on: EChartsInstance['on'] = useCallback((action, callback) => { + const on: EChartsInstance['on'] = useCallback((action, callback, options) => { const echartsInstance = echartsInstanceRef.current; + if (!echartsInstance) { + return; + } + // Create a unique key for this handler const handlerKey = `${action}-${callback.toString()}`; @@ -240,27 +267,53 @@ export function useEchart({ // Store the wrapper function so we can remove it later activeHandlers.current.set(handlerKey, zoomHandler); - echartsInstance?.on('datazoom', zoomHandler); + echartsInstance.on('datazoom', zoomHandler); break; } default: { activeHandlers.current.set(handlerKey, callback); - echartsInstance?.on(action, callback as (...args: any) => void); + options?.useCanvasAsTrigger + ? echartsInstance.getZr().on(action, callback) + : echartsInstance.on(action, callback as (...args: any) => void); } } }, []); + const showTooltip: EChartsInstance['showTooltip'] = useCallback((x, y) => { + const echartsInstance = echartsInstanceRef.current; + + if (!echartsInstance) { + return; + } + + echartsInstance.dispatchAction({ + type: 'showTip', + x, + y, + }); + }, []); + const hideTooltip = useCallback(() => { const echartsInstance = echartsInstanceRef.current; - echartsInstance?.dispatchAction({ + + if (!echartsInstance) { + return; + } + + echartsInstance.dispatchAction({ type: 'hideTip', }); }, []); const resize = useCallback(() => { const echartsInstance = echartsInstanceRef.current; - echartsInstance?.resize(); + + if (!echartsInstance) { + return; + } + + echartsInstance.resize(); }, []); /** @@ -356,7 +409,14 @@ export function useEchart({ }, [ready, theme]); /** + * UPDATING OPTIONS --------------------- + * Sets the options on the instance when the options meaningfully change. + * + * The `notMerge` option set to true means that all of the current echarts + * components will be removed and new components will be created according + * to the new options object. * + * API docs: https://echarts.apache.org/en/api.html#echartsInstance.setOption */ useEffect(() => { const echartsInstance = echartsInstanceRef.current; @@ -390,6 +450,7 @@ export function useEchart({ removeSeries, resize, setupZoomSelect, + showTooltip, updateOptions, }; } diff --git a/charts/core/src/EventMarkers/BaseEventMarker/utils.ts b/charts/core/src/EventMarkers/BaseEventMarker/utils.ts index cafd1c2b2c..ec046d2e36 100644 --- a/charts/core/src/EventMarkers/BaseEventMarker/utils.ts +++ b/charts/core/src/EventMarkers/BaseEventMarker/utils.ts @@ -1,3 +1,4 @@ +import { Theme } from '@leafygreen-ui/lib'; import { borderRadius, color, @@ -9,10 +10,30 @@ import { } from '@leafygreen-ui/tokens'; import { SeriesOption } from '../../Chart'; -import { infoIcon, warningIcon } from '../iconsSvgPaths'; import { EventLevel, GetMarkConfigProps } from './BaseEventMarker.types'; +const dataUriMap: Record> = { + [Theme.Dark]: { + info: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAATESURBVHgBxVddTJtVGH7PV+haWkcn8S9ZoRAQsi1alswLooGpF85E0yVbpt6MxVsNeKXeKCNeaGIicyYmJmblQiOBxGaLk4upEJd5wQU1CuEvUMYMm5PRzZb+QHt2nkO/9mu/09F2S/YkTb/vPd857znvz/O+h1GJ6PL5XCmy+cRjJ+Pcy0nzEHHX9igLM0qHOLEgMRq3UDwwFgiES1mX7fRBl+8NTzrNezjTunMKS4Lfwuj0WOCHEFWyAZw4nbZ/zBnv1WW3I1FaC9+hcCRCieQmbaVSUl5lsZDDbiOn3U51rt1U63TkFHA2oGmx08UswtTKxak5/caJPHi/cWudrq7+S/FkkkqBzWql+qcepyce3aOLQsIah1XWMG2gw/eWt4qnf4TyuDjl9OIyRWMxqgTYyDMtTbTLWi03kWLa0SuB74NFN2A8+Y21dVr8ZzVr5koB9zzdsJfqanfLTRRaguWUC59z2ySUr92+I0/+IIFNZFwiNhFv12OiSv8gE3DS7HPL14ou5HTU0JHODmr2uOnJx+qkbCG0QgvLKzQ5NUfXb/6nnLd4bZVcTifc4YEuIXoPcmkBmD7FaQnPE1OzRYPt1PHX6NirL5OzpkY5HtnYoJGLl+jc8AXlODLlYFuLfBauaIQrLHhxtx74Qvx5Ee34qU799Scf0osdz5G1ujpP4S2RlhgHMObd10ovHGqnX/+YoOTmZt46m1tbZNtllelKnLPl2alR1uXrdqV4fP1ep//2s4+kyY24fnONTrzzgXz+6dwZk1Xglrff7zethcw4tL+VwJ4WFmvUUhQHvUqSUSmH2QuVS6vU2HOWiJrTFHNOHX/dJIcO6AKrgtqriFMnBhD5hUCQwecqwOxDX30q/u1FY+LYkZdoWMREJLqRJ4euDFt2aoyYV55iw3yKdmEq1eIwv3/kAo2OX6HLE0EqBj1jChH+Pyr/BU0L0svQbTQWN33Y3FCvXDg4PUu/T0xKP29/51a6SY4p5ImMq6Fb0yucivGaPXuVi74iTvXuyRPZd2RDMehcYUROF3dp9JChIR3wAM4uBHx9v1gImVk1p4uFRRBSCI/IT/PkFbpfzIeummR6CkO3JkLxT7zUPuIwffiziHKVfyEzbg51QGUtpF9wes4kByUDovYENRGJY3jJlEvTAiMXfzHJkXpnB4ey72f9QzIzCjEs5qqKk0HXeIaKE0uIyHKoeCfsTMUoSPE92ljAH2aMBiFAG6VCT//nZcUDvsUcFbI6GPnRE8hwbGw7MCNc0YsqBZpE1TICVe38pXE5q6XRnVcRjUBsfBcYpf4vvzFVQgCnR2MCiHJ8NDTzdzjbET3ve3NA9Ps9cMHkzELRVgzEgpLb4smxHwJwXpwa1FzI+zqQegfbmkVDYhWVmJ+5fH6od9sQGSAW0jwuWzL0BPfqiirBvqYGQ1+Ya8myTIhYEKRwGLmJ3g0TVORULrabUndBU5q7I+zQlifpr/mlku8DhXCImNrfVC/NTqW05Toe6sUkt4lu1xYl+hCYukxezUSWoHSjfzBezdDrocmAqY1XMwRclZboK+tqlr8R0TET9YnifZJKhrgts/Sg4PmBii+n5o1kr+ddoot6lnO4x3A9ZySu5xz+Let6fhfk1VEC+YDPBgAAAABJRU5ErkJggg==', + warning: + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAROSURBVHgBxVfNTxtHFH8zXrANBDYF8dFQsrghImkFTk9VVQmnl17dW9pL+Q/snnoEbr2VHnsCLlV6qtVbL60jVVVPDfQzaivikEQoUQgLMfgDeyfzG3vXi+NlJyRSftLC7Hh23se89+b3GGkilU6bdYql5XCOCZEUxC0iYTZ+ZTYjpyCIrROjGxEq5/K5nK2zLwtbkEpfsxxHZATj8y2BWliNMFrK564X6DQKwGLHiS8IJrLu3F7xgHbsfbKLRapUj6hWr6t5IxKh3niM+uJxGjT7aaCvtyVAsGXOS0tBHmGdhUurBf0kiCy8P3i8S1vbD6lcrZIOYt3dNDE2TCOvnXWnCtIbVzt54xkF3kt/kjSE8x2El6WVf2/eoYNSiU4DKDIzlaBod5dSos74R7/kvlkPVMBv+YOdXdq8v+25+bTA8Vw8P06DA/1KiXZPsJZweeYidhPCd/b2leUvE1CieSRSifIVNya4u0AFXNPt/965p7Xpl5cnaGV2Umvt5r1tFbgSFmS58xH8Ua4nuo7xzVv/U7VWC91wfnyIvpgep2R/D+0dOfSrXTxxvSOEyp6xoUH4/d3EpbfXCrf+tJUH6oKURoh2nUg3uwxauPi6946x2RUJ/e6gVFYylEJOI70jqfS8KaimrP9nc0sr6D5/c5TSo16KUSzCqSKjN7/zJPRbKHFueEh6gU8nLl34mtepjPKqioyO9VZPlLKJESqUqjT54+/qsWt1ylgjWl6ADMhCVUVp5yRoDj8g8nWwMCXdbRhSgYr3rO8dKuELU+e09vDJmuOMWBKj4mF4sYH1CL4gZCdH1Jow2E8O1H9ZppPcLbc4mzDA+jCszISnZaV51JDN3RsuLPiQbidZ7yI1eEY+/SeuackSJidN6BYcQMdTLjjIBAao2UGA5fCAH6YRvD7MCy1ZzJZBSAUMcXMFwV90XEAheAUPBLZjZdYK3K+vJ94QL2VzGYobeBk409txMay34p0jG8UoyFJ8k7VGO/4G8gJIsrOOLMjjpXldHkN7yfUDhejsD7/JQrShClEnBJVon6wbPEKxHM4CNKr9GDLWcKD1/hiwjzpfXhCenTzuBchwKRvIK8/nVm3GaA0ToFF+JAc6H4u7+e0PZmj3wyuBSgJzbfHhyWC0Ck5gYCzr8bJ0YgaE4f7DR15R+uyvLdrYP6QXwerdR94Y1rs8UfpvqaFHE++nP16WfD+DywKc4EWpWDuQeu9MX5D8sJuEEF/9/P236jr2CpFB0UWkBbRMjI/RywYoWbQRYwWDVxbdeU8BxIIsClehBNx0OXH+xOKkiwYpfaONlLZ6hBBaXqU//rut3Q+0o1c2Km8lJjzLQ2m5i1famLSUmDdrVFlEYLpzqjWTZAJZAv7gb81i0UZ+w9X+1gwBhzN/rtbsuCLXLClmUV7en5I2ZLfMnDVZ55dP3Zw+q4jXnqcki5qVLNs61p4zku25wPk+V3v+FLqi4Iq8Yg11AAAAAElFTkSuQmCC', + }, + [Theme.Light]: { + info: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAS6SURBVHgBxVfPUxxFFH49ULC7KJDgmgISloREkpAgYETzgwpzUOPFgvJqlR5zMnAxpbEEqmJpLrr+B8nBo8HyoClz2GDEqKWAWImibgIRSGkIAUp2lxQ77ft6d4fdmR6yS1KV7zIz3T39Xr/3+nvvCcoTkdHRyqJErIvIOCqFbCFL1pMQlWpSygUyxKSQYozIGkr6Ap+bra0L+ewr7iv4ypX6IiFOSCv5hi0wr43F2STRgHnw4OT667wE48Qr8T4pqSczVlleTlWbN1NFeQX5SkqouLhYja+urtJ/sRgtx5bpzvw8LSwtrQmQFE76/QNeFtEqgFMbJCP8Wo/vLcEghbZuI19pKeWDxMoKTU3/Tf/cvp0ZmrRImDpruBSIDA+3GIYYhHAI3Nu4mx4LBGgjgCLj166qp1KiqLjbbG8f81Qg++Rbgk9SQyhkm3mjgHsmrkeVa0hjCVsB+NxIxEchHH5ueqqRHiYmolF2yb8pJXz+1kxM2MdTAZc2e+OOBs+NYvE4Xf7hJ/bxLZpLnYrqams5Rqppz64d9AQrrwOsubi0CHfUF8XjfTzUi3FlgbTpb+C9vbXNM9gGv7pIFyKXWYmEdj7g99Exs4O6X35BO4+bMjL+i3pnV2yHKwx1eiJopKJdJxynPvVhmM5/eTFHeFnAR8GqTVnrEmrNqTNh9Y8TCGbIAAwp1fUWkUik0vCV3l3v9BB+c2Y2ZwyCP+p/W70ff+s9WnZYpW5rDb1/sse1F27Ej6MjsP2CVerfbhT5SrowAZLRCT/PZncKB5ZjawL9fr9r/ub0LA2yNZyAjAqWRZIUtReD2/FVpQkeBNnX7HMdYOLevg/U0ysmLlz6ll4yj3Bs5CqIQF0EWwrjKLuCEwvBn2WuDX7787rLtADMj0DreO4APdO8j7wA5b75/mfXeMXj5eopLauFLcBZjR2iY7up6Vntxrt3NrDgJr56Nel1M+ymW9q1OvfZrjYE3750htMx3tSMXgHwwKeffWF/BwJ+8sLcnXnXmC2L48CgRwxDFROU4mwngh6sVgjq0m7Khi2LryJbQEziPXHvnmthqLaaHhQhjQJgRAVLMhMKUtwInnai4/kDVMb06gQYMPtkodqaHEbMANdvzy53XkHhAgjDGDMEyUv4yCQW5wYvdna4xtv276PXXn3F/sY7boYTxzqP8J13K5ZOzZSUNJSi4tKSG7gNXlT87pmPVfYrBDD96fWomMFpeZNhmiaC8BwGUEbp8M6bx1W6LUQ4/tEhI0MIcRY1gbqGljDCeKKGswMkC3DF6ZO9iv3gfy9gDmtw8oAmdnD6TJ3I5h9QimQmh74bDrNaJ+CCtv3NnqXY3PxdpuiocgkYEMB1DW2rZmp+VisYwNUb+XVcKWFJ+sQ8dKgnR4F0WlYlGXJ2Y8NOepi4+sfEWl2YVZLZTIhYQMGIBTATftCRU6FQRWn0r9yiNKtHuG9Z3ry3Ke9+wAnE07WJ39fKckt2m4cPe5flthKPsjGxlUjxQz8CMzOWac1QOyB9Z7dmoHKwqbM1Q8BxydRfUGuWo0jKGv38+jrli1S3fM6SIrzh5tSlCDculEh0sTKdnMefVoVMdnvOSY3JZSzJ7TkV0J7/D7iAJAXxV4qDAAAAAElFTkSuQmCC', + warning: + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQQSURBVHgBxVdLT1NBFD4zrbRFKURFI2poNKFGo4ILEzVR79rE6C/Qf4AL98DaDe50pwvdSjSuKyboRgU1EGssKdGQ8JCUAn0Qesf5pp2hLfe2wyPxS5o7M3d6z3POfIeRJRLj4x2BQu4OEb8hmOglV8SIsQ71UogMcZZmgk0QuaOlcOuI09eXsfkuayr448dYgLF+4ZbuG4FWH2bPSkRDzpUr6cb7/ATD4mJ+QAh6oNc6olE6dPAgtUfbKdzSQsFgUK1vbGzQai5Ha7k1+ru0RJlsdlOAoOFSJDLk5xFPBWA1J5GQwxjmRzs7qfvESQqHQmSDQrFIM39+09zCgl5Ku8QcL29sUSAxNtbLOXsF4RB4Nn6GDrS20k4ARb5NTaqnUiIQvOtcvjzhq0C15Uc7j9Dp7m7j5p0C4UlOp1RoyMMTRgHEnBfy4xCOOJ/ridNeIplKyZDMl5UIR/p0TnC9AQlHFbfHT522+ujio0c0PzBgtRferORQLJDPmz8pBeB6ne0Xzp6zcnv29WvKvHxZfr540XQ/vol8AgSjB5BpFAgQKY2Q7TaZ7q6s0NLTp2aOMdaaAckMGUqwEMpgnkgkOgSJ+5jgqNkAlm/MztYoZOOFGhmc7qm8C4Rb7mCOImNjPQRDWLCri2Jv36ofb2tTStl4ATLapSwSpEo7R23HC2S+DZaePFGC9kkFgpVfKB7fEpZGOKxlMX5DhkJeLBL7W/c3/SOsz7554/senqkOjR/a26LqKVy3V3pA3mpEVtUO1jfDnMWxNKHmTBa+yg3X7OgVk8mG1mvkP31Sv0YwsmQecLKEbcEBbHMB4IpMULlm+wHFBh6oRqOMb+YFI4tRRvqCpeWwt7C+Tgd8wuBlERRSXpEl1EsYcgFH1AvgDmUrRFrmAH3FeDm77LkZ1vtl9moiQbnPnz3f6XrhBRAXgHE+wRmJd5gslq/LGjQ62zj/p96/N4XIC34lunI1U0nQKC8V1keQB8uSRlWIg0F9ya1XTsNPAa8SDRmGsoXDI9xxHCThc8xBo6pRn3j1H0/fukXT1683LD75uhBpGYyxZ+AEKutcxoflcegHhzt+rMsUpc6HDynU00O7QfT2bTOG9ZonSvcPKUX0y9EPY8NSrX5UqUvnL+yaitUDR+/L929KCVfQY+fq1fJ1rDe4xfVB+UhjQ2omTXsN8EJNTikSGdTrRgHkAggjNsBNkz+TDYuTLRQpTf2qJaVVPUJTWg6KZtsP1AMFZyr5Y5OWu+Kuc+2aPy03SvzPxsQoIakaD7UMIjH1mm7NwB1wUqpbM5RyVNP61gwJh5hvqzWrUaTsjUE5vEe2KHfLz13BhnfcnG5RRBJIKhQkhxM35T1+URGZ6vZcXmqyuEyUZHtO22jP/wHqFDCi+Qr9/wAAAABJRU5ErkJggg==', + }, +}; + +/** + * PNG symbols gotten from designs. Custom Echarts symbols have to be image + * URLs, data URIs, or vector paths. + */ +const generateSymbolDataUri = (level: EventLevel, theme: Theme) => { + return `image://${dataUriMap[theme][level]}`; +}; + export function getMarkConfig({ name, theme, @@ -27,6 +48,7 @@ export function getMarkConfig({ backgroundColor: color[theme].background[Variant.InversePrimary][InteractionState.Default], color: color[theme].text[Variant.InversePrimary][InteractionState.Default], + distance: type === 'line' ? [0, -spacing[1400]] : undefined, fontFamily: fontFamilies.default, fontSize: 12, fontWeight: fontWeights.regular, @@ -79,14 +101,11 @@ export function getMarkConfig({ color: level === EventLevel.Warning ? color[theme].icon[Variant.Error][InteractionState.Default] - : color[theme].icon[Variant.Primary][InteractionState.Default], + : color[theme].icon[Variant.Secondary][InteractionState.Default], type: 'solid', width: 1, }, - symbol: - level === EventLevel.Warning - ? [warningIcon, 'none'] - : [infoIcon, 'none'], + symbol: [generateSymbolDataUri(level, theme), 'none'], symbolSize: [16, 16], symbolRotate: 360, // Icon shows upside down without this }, @@ -109,7 +128,7 @@ export function getMarkConfig({ }, }, symbolSize: [16, 16], - symbol: level === EventLevel.Warning ? warningIcon : infoIcon, + symbol: generateSymbolDataUri(level, theme), }, } as SeriesOption; } diff --git a/charts/core/src/EventMarkers/iconsSvgPaths.ts b/charts/core/src/EventMarkers/iconsSvgPaths.ts deleted file mode 100644 index 7284f485ec..0000000000 --- a/charts/core/src/EventMarkers/iconsSvgPaths.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * SVG carat symbol gotten from designs. Custom Echarts symbols have to be image - * URLs, data URIs, or vector paths. - */ -export const warningIcon = - 'image://data:image/png;base64,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'; - -export const infoIcon = - 'image://data:image/png;base64,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'; diff --git a/charts/core/src/Line/Line.tsx b/charts/core/src/Line/Line.tsx index 0e87e919fe..3ca6124986 100644 --- a/charts/core/src/Line/Line.tsx +++ b/charts/core/src/Line/Line.tsx @@ -1,5 +1,4 @@ import { useEffect } from 'react'; -import { colors } from '@lg-charts/colors'; import { useSeriesContext } from '@lg-charts/series-provider'; import { useDarkMode } from '@leafygreen-ui/leafygreen-provider'; @@ -14,12 +13,9 @@ export function Line({ name, data }: LineProps) { const { chart: { addSeries, ready, removeSeries }, } = useChartContext(); - const { getSeriesIndex, isChecked } = useSeriesContext(); - - const themedColors = colors[theme]; - const colorIndex = getSeriesIndex(name) % themedColors.length; // loop through colors if more lines than available colors - const color = themedColors[colorIndex]; + const { getColor, isChecked } = useSeriesContext(); + const color = getColor(name, theme); const isVisible = isChecked(name); useEffect(() => { @@ -32,11 +28,11 @@ export function Line({ name, data }: LineProps) { data, lineStyle: { ...defaultLineOptions.lineStyle, - color, + color: color || undefined, }, itemStyle: { ...defaultLineOptions.itemStyle, - color, + color: color || undefined, }, }); } else { diff --git a/charts/core/src/XAxis/XAxis.tsx b/charts/core/src/XAxis/XAxis.tsx index 2e86483c26..773a36e44f 100644 --- a/charts/core/src/XAxis/XAxis.tsx +++ b/charts/core/src/XAxis/XAxis.tsx @@ -33,7 +33,6 @@ const getOptions = ({ width: 1, }, }, - // @ts-expect-error TODO: axisLabel: { show: true, fontFamily: fontFamilies.default, diff --git a/charts/core/src/XAxis/XAxis.types.ts b/charts/core/src/XAxis/XAxis.types.ts index 88384d958b..28bb8e990b 100644 --- a/charts/core/src/XAxis/XAxis.types.ts +++ b/charts/core/src/XAxis/XAxis.types.ts @@ -1,3 +1,5 @@ +import type { AxisLabelValueFormatter } from '../Echart/Echart.types'; + export const XAxisType = { Log: 'log', Time: 'time', @@ -24,5 +26,5 @@ export interface XAxisProps { * formatter: (value, index) => `${value}GB` * ``` */ - formatter?: (value: string, index: number) => string; + formatter?: AxisLabelValueFormatter | string; } diff --git a/charts/core/src/YAxis/YAxis.tsx b/charts/core/src/YAxis/YAxis.tsx index 9c9c6479a7..5f57ff6dde 100644 --- a/charts/core/src/YAxis/YAxis.tsx +++ b/charts/core/src/YAxis/YAxis.tsx @@ -33,7 +33,6 @@ const getOptions = ({ width: 1, }, }, - // @ts-expect-error TODO: axisLabel: { show: true, fontFamily: fontFamilies.default, diff --git a/charts/core/src/YAxis/YAxis.types.ts b/charts/core/src/YAxis/YAxis.types.ts index 4fa890a307..e7f2cf6f62 100644 --- a/charts/core/src/YAxis/YAxis.types.ts +++ b/charts/core/src/YAxis/YAxis.types.ts @@ -1,3 +1,5 @@ +import type { AxisLabelValueFormatter } from '../Echart/Echart.types'; + export const YAxisType = { Log: 'log', Time: 'time', @@ -28,5 +30,5 @@ export interface YAxisProps { *} * ``` */ - formatter?: (value: string, index: number) => string; + formatter?: AxisLabelValueFormatter | string; } diff --git a/charts/core/src/constants.ts b/charts/core/src/constants.ts new file mode 100644 index 0000000000..00e9210545 --- /dev/null +++ b/charts/core/src/constants.ts @@ -0,0 +1,15 @@ +import { TooltipOption } from 'echarts/types/dist/shared'; + +export const CHART_TOOLTIP_CLASSNAME = 'lg-chart-tooltip'; + +// Adds vertical dashed line on hover, even when no tooltip is shown +export const DEFAULT_TOOLTIP_OPTIONS = { + tooltip: { + axisPointer: { + z: 0, // Prevents dashed emphasis line from being rendered on top of mark lines and labels + }, + show: true, + trigger: 'axis', + formatter: () => '', + } as TooltipOption, +}; diff --git a/charts/core/tsconfig.json b/charts/core/tsconfig.json index 0f776e1771..1e13eb328d 100644 --- a/charts/core/tsconfig.json +++ b/charts/core/tsconfig.json @@ -31,6 +31,9 @@ { "path": "../../packages/icon" }, + { + "path": "../../packages/icon-button" + }, { "path": "../../packages/leafygreen-provider" }, diff --git a/charts/drag-provider/CHANGELOG.md b/charts/drag-provider/CHANGELOG.md index ea5145c461..d88f55d84a 100644 --- a/charts/drag-provider/CHANGELOG.md +++ b/charts/drag-provider/CHANGELOG.md @@ -1,5 +1,43 @@ # @lg-charts/drag-provider +## 1.0.2 + +### Patch Changes + +- Updated dependencies [4e7a6b536] + - @lg-charts/core@1.2.0 + +## 1.0.1 + +### Patch Changes + +- Updated dependencies [4d350c5fb] + - @lg-charts/core@1.1.0 + +## 1.0.0 + +### Minor Changes + +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [21371bddd] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @lg-charts/chart-card@1.0.0 + - @lg-charts/core@1.0.0 + ## 0.2.8 ### Patch Changes diff --git a/charts/drag-provider/package.json b/charts/drag-provider/package.json index e2bcc92070..37d69018d1 100644 --- a/charts/drag-provider/package.json +++ b/charts/drag-provider/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/drag-provider", - "version": "0.2.8", + "version": "1.0.2", "description": "lg-charts DragProvider Component", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", diff --git a/charts/legend/CHANGELOG.md b/charts/legend/CHANGELOG.md index 87a37556ee..d091481d63 100644 --- a/charts/legend/CHANGELOG.md +++ b/charts/legend/CHANGELOG.md @@ -1,5 +1,35 @@ # @lg-charts/legend +## 1.0.0 + +### Minor Changes + +- 21371bddd: [LG-5091](https://jira.mongodb.org/browse/LG-5091): add `customColors` prop to `SeriesProvider` to enable customizing chart component colors +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [21371bddd] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @lg-charts/series-provider@1.0.0 + - @leafygreen-ui/checkbox@17.0.0 + - @leafygreen-ui/emotion@5.0.0 + - @leafygreen-ui/palette@5.0.0 + - @leafygreen-ui/tokens@3.0.0 + - @leafygreen-ui/lib@15.0.0 + ## 0.2.5 ### Patch Changes diff --git a/charts/legend/package.json b/charts/legend/package.json index 216a5edd65..f556cc9784 100644 --- a/charts/legend/package.json +++ b/charts/legend/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/legend", - "version": "0.2.5", + "version": "1.0.0", "description": "lg-charts Legend", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", @@ -20,7 +20,6 @@ "@leafygreen-ui/lib": "workspace:^", "@leafygreen-ui/palette": "workspace:^", "@leafygreen-ui/tokens": "workspace:^", - "@lg-charts/colors": "workspace:^", "@lg-charts/series-provider": "workspace:^" }, "peerDependencies": { diff --git a/charts/legend/src/LegendCheckbox/LegendCheckbox.tsx b/charts/legend/src/LegendCheckbox/LegendCheckbox.tsx index 42300cd15d..90bad9459a 100644 --- a/charts/legend/src/LegendCheckbox/LegendCheckbox.tsx +++ b/charts/legend/src/LegendCheckbox/LegendCheckbox.tsx @@ -1,5 +1,4 @@ import React, { forwardRef } from 'react'; -import { colors } from '@lg-charts/colors'; import { useSeriesContext } from '@lg-charts/series-provider'; import Checkbox from '@leafygreen-ui/checkbox'; @@ -11,11 +10,9 @@ import { LegendCheckboxProps } from './LegendCheckbox.types'; export const LegendCheckbox = forwardRef( ({ className, name, ...rest }, fwdRef) => { const { theme } = useDarkMode(); - const { getSeriesIndex } = useSeriesContext(); + const { getColor } = useSeriesContext(); - const themedColors = colors[theme]; - const colorIndex = name ? getSeriesIndex(name) % themedColors.length : -1; // loop through colors if more checkboxes than available colors - const checkboxColor = themedColors[colorIndex]; + const checkboxColor = name ? getColor(name, theme) : undefined; const showFilled = !!(rest.checked || rest.indeterminate); return ( diff --git a/charts/legend/tsconfig.json b/charts/legend/tsconfig.json index 3baed1d5bd..578f33f51b 100644 --- a/charts/legend/tsconfig.json +++ b/charts/legend/tsconfig.json @@ -18,9 +18,6 @@ "**/*.stories.*" ], "references": [ - { - "path": "../colors" - }, { "path": "../series-provider" }, diff --git a/charts/series-provider/CHANGELOG.md b/charts/series-provider/CHANGELOG.md index 026c88e554..ca81b26c84 100644 --- a/charts/series-provider/CHANGELOG.md +++ b/charts/series-provider/CHANGELOG.md @@ -1,5 +1,30 @@ # @lg-charts/series-provider +## 1.0.0 + +### Minor Changes + +- 21371bddd: [LG-5091](https://jira.mongodb.org/browse/LG-5091): add `customColors` prop to `SeriesProvider` to enable customizing chart component colors +- 0757cfbfc: Updates Typescript build to TS5.8 + +### Patch Changes + +- 0757cfbfc: Adds `@lg-tools/build` as a dev dependency +- 0757cfbfc: Adds missing `@lg-tools/` devDependencies. + Updates `build`, `tsc` & `docs` scripts to use `lg-build *` cli +- 0757cfbfc: Updates `types` entry point to `./dist/types`. + Removes redundant `compilerOptions` from TSConfig +- 0757cfbfc: Updates `main` entry point in package.json to `./dist/umd` +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [0757cfbfc] +- Updated dependencies [21371bddd] +- Updated dependencies [0757cfbfc] + - @leafygreen-ui/leafygreen-provider@5.0.0 + - @lg-charts/colors@1.0.0 + - @leafygreen-ui/lib@15.0.0 + ## 0.2.2 ### Patch Changes diff --git a/charts/series-provider/README.md b/charts/series-provider/README.md index ddcf2d607a..d3317935ab 100644 --- a/charts/series-provider/README.md +++ b/charts/series-provider/README.md @@ -51,9 +51,10 @@ const App = () => { ## Props -| Name | Description | Type | Default | -| -------- | --------------------------------------------------------------------------------------------------------- | --------------- | ------- | -| `series` | An array of series names representing the data series to be displayed in the descendant charts components | `Array` | | +| Name | Description | Type | Default | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | +| `customColors` | An optional object mapping each theme to an array of custom colors for the series. If not provided, default colors based on the current theme will be used | `Array` | | +| `series` | An array of series names representing the data series to be displayed in the descendant charts components | `Array` | | ## `useSeriesContext` @@ -66,6 +67,7 @@ import { useSeriesContext } from '@leafygreen-ui/series-provider'; const ChartComponent = () => { const { + getColor, getSeriesIndex, isChecked, isSelectAllChecked, diff --git a/charts/series-provider/package.json b/charts/series-provider/package.json index b6b1c68831..f339bb68a3 100644 --- a/charts/series-provider/package.json +++ b/charts/series-provider/package.json @@ -1,6 +1,6 @@ { "name": "@lg-charts/series-provider", - "version": "0.2.2", + "version": "1.0.0", "description": "lg-charts SeriesProvider Component", "main": "./dist/umd/index.js", "module": "./dist/esm/index.js", @@ -21,6 +21,10 @@ "bugs": { "url": "https://jira.mongodb.org/projects/PD/summary" }, + "dependencies": { + "@leafygreen-ui/lib": "workspace:^", + "@lg-charts/colors": "workspace:^" + }, "peerDependencies": { "@leafygreen-ui/leafygreen-provider": "workspace:^" }, diff --git a/charts/series-provider/src/SeriesContext.spec.tsx b/charts/series-provider/src/SeriesContext.spec.tsx index 9ca95fd6e0..5e759c468d 100644 --- a/charts/series-provider/src/SeriesContext.spec.tsx +++ b/charts/series-provider/src/SeriesContext.spec.tsx @@ -1,4 +1,9 @@ import React from 'react'; +import { + colors as defaultColors, + type DarkColor, + type LightColor, +} from '@lg-charts/colors'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -6,6 +11,7 @@ import { SeriesProvider, useSeriesContext } from './SeriesContext'; const TestComponent = () => { const { + getColor, getSeriesIndex, isChecked, isSelectAllChecked, @@ -26,6 +32,8 @@ const TestComponent = () => {
    {isSelectAllIndeterminate().toString()}
    +
    {getColor('Test series', 'light')}
    +
    {getColor('Test series', 'dark')}