From 42f7cb63af5e059ccdee4ca007d258a93372a7d7 Mon Sep 17 00:00:00 2001 From: clintcs <114178960+clintcs@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:17:14 -0500 Subject: [PATCH 1/6] Prepare for the elements manifest --- .changeset/twenty-pandas-brake.md | 21 + .husky/pre-push | 4 +- .stylelintrc.js | 2 + .vscode/settings.json | 8 +- CONTRIBUTING.md | 69 +- eslint.config.js | 18 +- package.json | 73 ++- pnpm-lock.yaml | 602 +++++++++++++++++- src/accordion.ts | 33 +- src/button-group.button.ts | 17 +- src/button-group.ts | 41 +- src/button.ts | 19 +- src/checkbox-group.styles.ts | 2 +- src/checkbox-group.ts | 49 +- src/checkbox.styles.ts | 2 +- src/checkbox.ts | 54 +- src/drawer.styles.ts | 7 +- src/drawer.ts | 14 +- src/dropdown.option.styles.ts | 2 +- src/dropdown.option.ts | 46 +- src/dropdown.styles.ts | 25 +- src/dropdown.ts | 130 ++-- src/eslint/plugin.ts | 46 +- ...nsistent-reference-element-declarations.ts | 2 +- ...istent-test-fixture-variable-declarator.ts | 6 +- .../rules/event-dispatch-from-this.test.ts | 48 ++ src/eslint/rules/event-dispatch-from-this.ts | 42 ++ .../no-glide-core-prefixed-event-name.ts | 10 +- .../rules/no-redundant-property-attribute.ts | 2 +- .../no-redundant-property-string-type.ts | 2 +- src/eslint/rules/no-space-press.ts | 4 +- .../rules/prefer-to-be-true-or-false.ts | 4 +- .../prefixed-lit-element-class-declaration.ts | 2 +- .../public-getter-default-comment.test.ts | 106 +++ .../rules/public-getter-default-comment.ts | 111 ++++ .../rules/public-member-return-type.test.ts | 72 +++ src/eslint/rules/public-member-return-type.ts | 50 ++ src/eslint/rules/slot-type-comment.test.ts | 77 +++ src/eslint/rules/slot-type-comment.ts | 96 +++ src/eslint/rules/string-event-name.test.ts | 43 ++ src/eslint/rules/string-event-name.ts | 44 ++ src/form-controls-layout.ts | 9 +- src/icon-button.styles.ts | 16 +- src/icon-button.ts | 8 +- src/icons/checked.ts | 4 +- src/icons/chevron.ts | 4 +- src/icons/magnifying-glass.ts | 4 +- src/icons/pencil.ts | 4 +- src/icons/severity-critical.ts | 4 +- src/icons/severity-informational.ts | 4 +- src/icons/severity-medium.ts | 4 +- src/icons/storybook.ts | 4 +- src/icons/x.ts | 4 +- src/inline-alert.styles.ts | 6 +- src/inline-alert.ts | 14 +- src/input.stories.ts | 18 +- src/input.styles.ts | 7 +- src/input.ts | 77 +-- src/label.styles.ts | 21 +- src/label.ts | 25 +- src/library/get-parent-class-name.ts | 17 + src/menu.button.styles.ts | 2 +- src/menu.button.ts | 10 +- src/menu.link.styles.ts | 2 +- src/menu.link.ts | 10 +- src/menu.options.styles.ts | 14 +- src/menu.options.ts | 4 +- src/menu.stories.ts | 2 +- src/menu.ts | 53 +- src/modal.icon-button.styles.ts | 2 +- src/modal.icon-button.ts | 8 +- src/modal.styles.ts | 6 +- src/modal.ts | 31 +- src/popover.stories.ts | 2 +- src/popover.styles.ts | 12 +- src/popover.ts | 31 +- src/radio-group.radio.ts | 38 +- src/radio-group.ts | 46 +- src/split-button.primary-button.ts | 10 +- src/split-button.primary-link.ts | 15 +- src/split-button.secondary-button.ts | 6 +- src/split-button.ts | 22 +- src/stylelint/plugin.ts | 9 + ...unprefixed-private-custom-property.test.ts | 73 +++ .../no-unprefixed-private-custom-property.ts | 70 ++ src/tab.group.styles.ts | 11 +- src/tab.group.ts | 20 +- src/tab.panel.styles.ts | 11 +- src/tab.panel.ts | 15 +- src/tab.ts | 38 +- src/tabs.stories.ts | 66 +- src/tag.styles.ts | 8 +- src/tag.ts | 6 +- src/textarea.styles.ts | 20 +- src/textarea.ts | 31 +- src/toasts.toast.styles.ts | 2 +- src/toasts.toast.ts | 7 +- src/toasts.ts | 21 +- src/toggle.styles.ts | 6 +- src/toggle.ts | 12 +- src/tooltip.container.ts | 10 +- src/tooltip.styles.ts | 14 +- src/tooltip.ts | 63 +- src/tree.item.icon-button.styles.ts | 6 +- src/tree.item.icon-button.ts | 7 +- src/tree.item.menu.styles.ts | 6 +- src/tree.item.menu.ts | 13 +- src/tree.item.styles.ts | 10 +- src/tree.item.ts | 70 +- src/tree.test.basics.ts | 2 +- src/tree.ts | 24 +- terser.js | 12 +- tsconfig.json | 4 +- vitest.config.js | 2 +- web-test-runner.config.js | 9 +- 115 files changed, 2621 insertions(+), 642 deletions(-) create mode 100644 .changeset/twenty-pandas-brake.md create mode 100644 src/eslint/rules/event-dispatch-from-this.test.ts create mode 100644 src/eslint/rules/event-dispatch-from-this.ts create mode 100644 src/eslint/rules/public-getter-default-comment.test.ts create mode 100644 src/eslint/rules/public-getter-default-comment.ts create mode 100644 src/eslint/rules/public-member-return-type.test.ts create mode 100644 src/eslint/rules/public-member-return-type.ts create mode 100644 src/eslint/rules/slot-type-comment.test.ts create mode 100644 src/eslint/rules/slot-type-comment.ts create mode 100644 src/eslint/rules/string-event-name.test.ts create mode 100644 src/eslint/rules/string-event-name.ts create mode 100644 src/library/get-parent-class-name.ts create mode 100644 src/stylelint/plugin.ts create mode 100644 src/stylelint/rules/no-unprefixed-private-custom-property.test.ts create mode 100644 src/stylelint/rules/no-unprefixed-private-custom-property.ts diff --git a/.changeset/twenty-pandas-brake.md b/.changeset/twenty-pandas-brake.md new file mode 100644 index 000000000..e9d5568a7 --- /dev/null +++ b/.changeset/twenty-pandas-brake.md @@ -0,0 +1,21 @@ +--- +'@crowdstrike/glide-core': minor +--- + +- Tab Panel no longer has an unused static `instanceCount` property. +- Toggle no longer has a `name` property. `name` only applies to form controls and was unused. +- Tree Item's `hasChildTreeItems` and `hasExpandIcon` properties and its `toggleExpand()` method have been marked private. + +Additionally, some internal changes we made to facillitate generating documentation programmatically forced us remove a few exported types and rename some custom properties: + +- Input no longer exports a `SUPPORTED_TYPES` interface. +- Toasts no longer exports a `Toast` interface. +- Tab Panel's custom properties have been renamed: + + ```diff + - --panel-padding-inline-end + + --padding-inline-end + + - --panel-padding-inline-start + + --padding-inline-start + ``` diff --git a/.husky/pre-push b/.husky/pre-push index dee339b11..093f7af24 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1,6 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -NODE_ENV=production pnpm typecheck && NODE_ENV=production pnpm test +NODE_ENV=production pnpm start +NODE_ENV=production pnpm test +NODE_ENV=production pnpm typecheck diff --git a/.stylelintrc.js b/.stylelintrc.js index 00e7d3ec5..667465faf 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -6,6 +6,7 @@ export default { 'stylelint-use-nesting', 'stylelint-use-logical', 'stylelint-order', + './dist/stylelint/plugin', ], rules: { // https://github.com/w3c/csswg-drafts/issues/9496 @@ -17,5 +18,6 @@ export default { 'no-descending-specificity': null, 'order/properties-alphabetical-order': true, 'prettier/prettier': true, + 'glide-core/no-unprefixed-private-custom-property': true, }, }; diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bafe9a75..f4c59d164 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { - "eslint.workingDirectories": [{ "mode": "auto" }], - "editor.formatOnSave": true, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "stylelint.validate": ["css", "postcss", "typescript"], "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "editor.formatOnSave": true, + "eslint.workingDirectories": [{ "mode": "auto" }], + "stylelint.validate": ["css", "postcss", "typescript"] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 33f0b4ba5..ac199a5a1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -146,44 +146,35 @@ Embrace encapsulation wherever you can. #### Avoid styling `:host` -Styling `:host` exposes the styles to consumers—allowing internal styles to be overridden. -Due to that, we do not recommend styling `:host` in our components, but rather using CSS variables targeting the tag directly or using a class name. +Styling `:host` exposes styles to consumers—allowing internal styles to be overridden. +Style classes directly instead: ```css /* ✅ -- GOOD */ -/* Target the button tag directly */ -button { - background-color: var(--button-background-color); -} - -/* Or use a class name `; } } ``` @@ -225,13 +214,7 @@ export default class GlideCoreExample extends LitElement { @customElement('glide-core-example') export default class GlideCoreExample extends LitElement { override render() { - return html` -
- - Details -
-
- `; + return html` `; } } ``` @@ -347,15 +330,15 @@ If you need elements from a specific slot, use [assignedElements()](https://deve #### Prefer using animations only when the user has no reduced motion preference The [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) media query is used to detect if a user has enabled a setting on their device to minimize inessential motion. -Our accessibility team recommends only enabling animations when the user doesn't prefer reduced motion. +Our accessibility team recommends only enabling animations when the user has that setting turned off. ```css /* ✅ -- GOOD */ .animation { - background-color: purple; + transform: translateX(100%); @media (prefers-reduced-motion: no-preference) { - animation: pulse 1s linear infinite both; + transition: transform 1s; } } ``` @@ -363,8 +346,8 @@ Our accessibility team recommends only enabling animations when the user doesn't ```css /* ❌ -- BAD */ .animation { - animation: pulse 1s linear infinite both; - background-color: purple; + transform: translateX(100%); + transition: transform 1s; } ``` @@ -552,7 +535,7 @@ There are many ways to target the root element of a component in CSS; however, w // ✅ -- GOOD css` .component { - background-color: red; + display: flex; } `; @@ -565,7 +548,7 @@ render() { // ❌ -- BAD css` div { - background-color: red; + display: flex; } `; @@ -616,4 +599,4 @@ So it's best to always override and decorate (using `@property`) inherited prope It helps clarify how different scripts are used in different contexts. It also neatly abstracts away specific script names from CI configuration. -In general, think of `:development` scripts as either long-running (`--serve`, `--watch`) or mutative (`--fix`, `--write`) and `:production` scripts as neither of those things. +In general, think of `*:development:*` scripts as long-running (`--serve`, `--watch`) and mutative (`--fix`, `--write`) and `*:production:*` scripts as neither. diff --git a/eslint.config.js b/eslint.config.js index 5493c591e..1d5a75c98 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -45,6 +45,11 @@ export default [ '@crowdstrike/glide-core/no-space-press': 'error', '@crowdstrike/glide-core/prefer-shadow-root-mode': 'error', '@crowdstrike/glide-core/prefixed-lit-element-class-declaration': 'error', + '@crowdstrike/glide-core/public-member-return-type': 'error', + '@crowdstrike/glide-core/public-getter-default-comment': 'error', + '@crowdstrike/glide-core/event-dispatch-from-this': 'error', + '@crowdstrike/glide-core/string-event-name': 'error', + '@crowdstrike/glide-core/slot-type-comment': 'error', // Enabling this rule would force us to `await` any function that returns a promise. // One example is a function that itself `await`s `updateComplete`. The rule is a bit @@ -289,7 +294,6 @@ export default [ // and other times something else depending on what it's chained with. ...typescript.configs.disableTypeChecked, }, - { files: ['src/**/*.test.ts', 'src/*.test.*.ts', 'src/*.*.test.*.ts'], rules: { @@ -307,6 +311,18 @@ export default [ '@crowdstrike/glide-core/no-skip-tests': 'error', '@crowdstrike/glide-core/no-to-have-attribute': 'error', '@crowdstrike/glide-core/prefer-to-be-true-or-false': 'error', + '@crowdstrike/glide-core/public-member-return-type': 'off', + '@crowdstrike/glide-core/public-getter-default-comment': 'off', + '@crowdstrike/glide-core/event-dispatch-from-this': 'off', + '@crowdstrike/glide-core/string-event-name': 'off', + '@crowdstrike/glide-core/slot-type-comment': 'off', + }, + }, + { + files: ['src/library/**'], + rules: { + '@crowdstrike/glide-core/public-member-return-type': 'off', + '@crowdstrike/glide-core/public-getter-default-comment': 'off', }, }, ]; diff --git a/package.json b/package.json index c84e0b30a..7d3126b71 100644 --- a/package.json +++ b/package.json @@ -11,58 +11,68 @@ }, "files": [ "dist", + "!dist/*.*.test.*.d.ts", + "!dist/*.*.test.*.js", + "!dist/*.stories.d.ts", + "!dist/*.stories.js", + "!dist/*.test.*.d.ts", + "!dist/*.test.*.js", + "!dist/cem-analyzer-plugins", "!dist/eslint", "!dist/icons/storybook.*", "!dist/storybook", - "!dist/*.test.js", - "!dist/*.test.*.d.ts", - "!dist/*.test.*.js", - "!dist/*.stories.js", - "!dist/*.stories.d.ts" + "!dist/stylelint", + "!dist/ts-morph" ], "exports": { "./*.js": { "types": "./dist/*.d.ts", "import": "./dist/*.js" }, - "./*.styles.js": null, - "./library/*": null, - "./icons/*": null, - "./styles/*": null, - "./label.js": null, - "./toasts.toast.js": null, + "./translations/*": null, "./tooltip.container.js": null, + "./toasts.toast.js": null, + "./styles/variables.css": "./dist/styles/variables.css", "./styles/fonts.css": "./dist/styles/fonts.css", - "./styles/variables.css": "./dist/styles/variables.css" + "./styles/*": null, + "./library/*": null, + "./label.js": null, + "./icons/*": null, + "./*.styles.js": null }, "scripts": { "start": "per-env", - "start:development": "storybook dev --config-dir .storybook --no-open --no-version-updates --port 6006", - "start:production": "rimraf ./dist && npm-run-all --parallel start:production:components start:production:storybook start:production:stylesheets --aggregate-output --print-label", - "start:production:components": "tsc --outDir ./dist && node ./terser.js", + "start:development": "npm-run-all --parallel --print-name start:development:*", + "start:development:storybook": "storybook dev --config-dir .storybook --no-open --no-version-updates --port 6006", + "start:production": "rimraf ./dist && npm-run-all --aggregate-output --print-label --parallel start:production:components start:production:storybook start:production:stylesheets", + "start:production:components": "tsc --noCheck --outDir ./dist && node ./terser.js", "start:production:figma": "pnpm dt export-variables && pnpm dt build-tokens && pnpm dt build-styles", "start:production:storybook": "storybook build --config-dir .storybook --disable-telemetry --output-dir ./dist/storybook", "start:production:stylesheets": "node ./esbuild.js", "format": "per-env", - "format:development": "prettier . --write && stylelint '**/*.styles.ts' --custom-syntax postcss-lit --fix", - "format:production": "prettier . --check && stylelint '**/*.styles.ts' --custom-syntax postcss-lit --no-color", + "format:development": "chokidar '**/*' --ignore 'dist/**' --ignore '.changeset/**' --ignore '.git/**' --ignore 'node_modules/**' --ignore 'pnpm-lock.yaml' --initial --silent --comand 'prettier --write --ignore-unknown {path} && stylelint {path}'", + "format:production": "prettier . --debug-check", "lint": "per-env", - "lint:development": "npm-run-all --print-name lint:development:*", - "lint:development:eslint": "tsc --outDir ./dist && eslint . --fix", + "lint:development": "npm-run-all --parallel --print-name lint:development:*", + "lint:development:eslint": "chokidar ./eslint-config.js ./src/eslint/** ./src/*.ts ./src/*.*.ts --initial --silent --command 'tsc --noCheck --outDir ./dist && eslint {path} --fix'", "lint:development:lit-analyzer": "lit-analyzer **/*.ts", - "lint:production": "npm-run-all --parallel --aggregate-output --print-label lint:production:*", - "lint:production:eslint": "tsc --outDir ./dist && eslint .", + "lint:development:stylelint": "chokidar ./.stylelintrc.js ./src/stylelint/** ./src/*.styles.ts ./src/*.*.styles.ts --initial --silent --command 'tsc --noCheck --outDir ./dist && stylelint {path} --custom-syntax postcss-lit --fix'", + "lint:production": "npm-run-all --aggregate-output --print-label --parallel lint:production:*", + "lint:production:eslint": "tsc --noCheck --outDir ./dist && eslint .", "lint:production:lit-analyzer": "lit-analyzer **/*.ts", - "typecheck": "tsc --noEmit", + "lint:production:stylelint": "tsc --noCheck --outDir ./dist && stylelint '**/*.styles.ts' --custom-syntax postcss-lit --no-color", "test": "per-env", - "test:development": "npm-run-all --parallel test:development:serve test:development:web-test-runner start:production:stylesheets", - "test:development:serve": "npx http-server dist/coverage/lcov-report --silent", - "test:development:web-test-runner": "web-test-runner --watch", - "test:development:vitest": "vitest --config ./vitest.config.js", - "test:development:vitest:comment": "Vitest is excluded from `test:development` because it muddies the console when running alongside Web Test Runner.", - "test:production": "npm-run-all --parallel test:production:* start:production:stylesheets --aggregate-output --print-label", - "test:production:vitest": "vitest run --config ./vitest.config.js", - "test:production:web-test-runner": "web-test-runner", + "test:development": "pnpm start:production:stylesheets && npm-run-all --parallel test:development:components test:development:serve-component-coverage", + "test:development:components": "web-test-runner --watch", + "test:development:lint-rules": "vitest --config ./vitest.config.js & chokidar './src/eslint/**' './src/stylelint/**' --ignore './src/eslint/rules/*.test.ts' './src/stylelint/*.test.ts' --initial --silent --command 'tsc --noCheck --outDir ./dist'", + "test:development:lint-rules:comment": "Excluded from `test:development` because Vitest muddies the console when running alongside Web Test Runner.", + "test:development:serve-component-coverage": "npx http-server dist/coverage/lcov-report --silent", + "test:production": "pnpm start:production:stylesheets && npm-run-all --aggregate-output --print-label --parallel test:production:*", + "test:production:lint-rules": "tsc --noCheck --outDir ./dist && vitest run --config ./vitest.config.js", + "test:production:components": "web-test-runner", + "typecheck": "per-env", + "typecheck:development": "tsc --outDir ./dist -w", + "typecheck:production": "tsc --outDir ./dist", "postinstall": "pnpm dlx playwright@1.49.1 install --with-deps", "prepare": "is-ci || husky install", "release": "changeset publish" @@ -106,6 +116,8 @@ "@web/test-runner-commands": "^0.9.0", "@web/test-runner-playwright": "^0.11.0", "chalk": "^5.3.0", + "chokidar-cli": "^3.0.0", + "comment-parser": "^1.4.1", "esbuild": "^0.25.0", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.1", @@ -123,6 +135,7 @@ "lit": "^3.2.1", "lit-analyzer": "^2.0.3", "minify-literals": "^1.0.10", + "node-html-parser": "^7.0.1", "npm-run-all2": "^7.0.2", "per-env": "^1.0.2", "postcss": "^8.4.49", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5285284f5..b7ff15684 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,7 +68,7 @@ importers: version: 8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2)) '@storybook/web-components-vite': specifier: ^8.5.3 - version: 8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0)) + version: 8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) '@stylistic/eslint-plugin': specifier: ^2.12.1 version: 2.12.1(eslint@9.17.0)(typescript@5.7.3) @@ -108,6 +108,12 @@ importers: chalk: specifier: ^5.3.0 version: 5.4.1 + chokidar-cli: + specifier: ^3.0.0 + version: 3.0.0 + comment-parser: + specifier: ^1.4.1 + version: 1.4.1 esbuild: specifier: ^0.25.0 version: 0.25.0 @@ -159,6 +165,9 @@ importers: minify-literals: specifier: ^1.0.10 version: 1.0.10 + node-html-parser: + specifier: ^7.0.1 + version: 7.0.1 npm-run-all2: specifier: ^7.0.2 version: 7.0.2 @@ -215,10 +224,10 @@ importers: version: 8.23.0(eslint@9.17.0)(typescript@5.7.3) vite: specifier: ^6.0.7 - version: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + version: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) vitest: specifier: ^3.0.4 - version: 3.0.5(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + version: 3.0.5(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) packages: @@ -350,6 +359,12 @@ packages: '@dual-bundle/import-meta-resolve@4.1.0': resolution: {integrity: sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==} + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -362,6 +377,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.24.2': resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} engines: {node: '>=18'} @@ -374,6 +395,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.24.2': resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} engines: {node: '>=18'} @@ -386,6 +413,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.24.2': resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} engines: {node: '>=18'} @@ -398,6 +431,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.24.2': resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} engines: {node: '>=18'} @@ -410,6 +449,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.24.2': resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} engines: {node: '>=18'} @@ -422,6 +467,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} engines: {node: '>=18'} @@ -434,6 +485,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} engines: {node: '>=18'} @@ -446,6 +503,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.24.2': resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} engines: {node: '>=18'} @@ -458,6 +521,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.24.2': resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} engines: {node: '>=18'} @@ -470,6 +539,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.24.2': resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} engines: {node: '>=18'} @@ -482,6 +557,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.24.2': resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} engines: {node: '>=18'} @@ -494,6 +575,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.24.2': resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} engines: {node: '>=18'} @@ -506,6 +593,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.24.2': resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} engines: {node: '>=18'} @@ -518,6 +611,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.24.2': resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} engines: {node: '>=18'} @@ -530,6 +629,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.24.2': resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} engines: {node: '>=18'} @@ -542,6 +647,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.24.2': resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} engines: {node: '>=18'} @@ -566,6 +677,12 @@ packages: cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} engines: {node: '>=18'} @@ -578,6 +695,12 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.24.2': resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} engines: {node: '>=18'} @@ -590,6 +713,12 @@ packages: cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} engines: {node: '>=18'} @@ -602,6 +731,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.24.2': resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} engines: {node: '>=18'} @@ -614,6 +749,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.24.2': resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} engines: {node: '>=18'} @@ -626,6 +767,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.24.2': resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} engines: {node: '>=18'} @@ -638,6 +785,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.24.2': resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} engines: {node: '>=18'} @@ -1486,6 +1639,10 @@ packages: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} + ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1506,6 +1663,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1625,6 +1786,13 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1687,6 +1855,10 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -1724,6 +1896,15 @@ packages: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} + chokidar-cli@3.0.0: + resolution: {integrity: sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==} + engines: {node: '>= 8.10.0'} + hasBin: true + + chokidar@3.5.2: + resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} + engines: {node: '>= 8.10.0'} + chokidar@4.0.1: resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} engines: {node: '>= 14.16.0'} @@ -1766,6 +1947,9 @@ packages: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cliui@5.0.0: + resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1820,6 +2004,10 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -1865,10 +2053,17 @@ packages: resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==} engines: {node: '>=12 || >=16'} + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + css-tree@3.1.0: resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1924,6 +2119,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -2008,9 +2207,22 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom5@3.0.1: resolution: {integrity: sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==} + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -2038,6 +2250,9 @@ packages: emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@7.0.3: + resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2111,6 +2326,11 @@ packages: peerDependencies: esbuild: '>=0.12 <1' + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.24.2: resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} engines: {node: '>=18'} @@ -2347,6 +2567,10 @@ packages: resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} engines: {node: '>=4.0.0'} + find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -2453,6 +2677,9 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + get-uri@6.0.4: resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} engines: {node: '>= 14'} @@ -2710,6 +2937,10 @@ packages: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-boolean-object@1.2.1: resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} engines: {node: '>= 0.4'} @@ -2751,6 +2982,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -3026,6 +3261,10 @@ packages: lit@3.2.1: resolution: {integrity: sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==} + locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -3037,6 +3276,9 @@ packages: lodash.camelcase@4.3.0: resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + lodash.deburr@4.1.0: resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==} @@ -3050,6 +3292,9 @@ packages: lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -3249,6 +3494,9 @@ packages: encoding: optional: true + node-html-parser@7.0.1: + resolution: {integrity: sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA==} + node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -3276,6 +3524,9 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-inspect@1.13.3: resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} engines: {node: '>= 0.4'} @@ -3365,6 +3616,10 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -3435,6 +3690,10 @@ packages: pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -3643,6 +3902,10 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + readdirp@4.0.2: resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} engines: {node: '>= 14.16.0'} @@ -3682,6 +3945,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requireindex@1.2.0: resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} engines: {node: '>=0.10.5'} @@ -3701,6 +3967,9 @@ packages: resolution: {integrity: sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==} engines: {node: '>= 0.8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.9: resolution: {integrity: sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A==} hasBin: true @@ -3783,6 +4052,9 @@ packages: engines: {node: '>=10'} hasBin: true + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3940,6 +4212,10 @@ packages: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} + string-width@3.1.0: + resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==} + engines: {node: '>=6'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3964,6 +4240,10 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4147,6 +4427,11 @@ packages: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} + tsx@4.19.2: + resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4426,6 +4711,9 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which-typed-array@1.1.18: resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} engines: {node: '>= 0.4'} @@ -4457,6 +4745,10 @@ packages: resolution: {integrity: sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==} engines: {node: '>=12.17'} + wrap-ansi@5.1.0: + resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==} + engines: {node: '>=6'} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -4504,6 +4796,9 @@ packages: utf-8-validate: optional: true + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -4513,10 +4808,16 @@ packages: engines: {node: '>= 14'} hasBin: true + yargs-parser@13.1.2: + resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@13.3.2: + resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -4762,102 +5063,153 @@ snapshots: '@dual-bundle/import-meta-resolve@4.1.0': {} + '@esbuild/aix-ppc64@0.23.1': + optional: true + '@esbuild/aix-ppc64@0.24.2': optional: true '@esbuild/aix-ppc64@0.25.0': optional: true + '@esbuild/android-arm64@0.23.1': + optional: true + '@esbuild/android-arm64@0.24.2': optional: true '@esbuild/android-arm64@0.25.0': optional: true + '@esbuild/android-arm@0.23.1': + optional: true + '@esbuild/android-arm@0.24.2': optional: true '@esbuild/android-arm@0.25.0': optional: true + '@esbuild/android-x64@0.23.1': + optional: true + '@esbuild/android-x64@0.24.2': optional: true '@esbuild/android-x64@0.25.0': optional: true + '@esbuild/darwin-arm64@0.23.1': + optional: true + '@esbuild/darwin-arm64@0.24.2': optional: true '@esbuild/darwin-arm64@0.25.0': optional: true + '@esbuild/darwin-x64@0.23.1': + optional: true + '@esbuild/darwin-x64@0.24.2': optional: true '@esbuild/darwin-x64@0.25.0': optional: true + '@esbuild/freebsd-arm64@0.23.1': + optional: true + '@esbuild/freebsd-arm64@0.24.2': optional: true '@esbuild/freebsd-arm64@0.25.0': optional: true + '@esbuild/freebsd-x64@0.23.1': + optional: true + '@esbuild/freebsd-x64@0.24.2': optional: true '@esbuild/freebsd-x64@0.25.0': optional: true + '@esbuild/linux-arm64@0.23.1': + optional: true + '@esbuild/linux-arm64@0.24.2': optional: true '@esbuild/linux-arm64@0.25.0': optional: true + '@esbuild/linux-arm@0.23.1': + optional: true + '@esbuild/linux-arm@0.24.2': optional: true '@esbuild/linux-arm@0.25.0': optional: true + '@esbuild/linux-ia32@0.23.1': + optional: true + '@esbuild/linux-ia32@0.24.2': optional: true '@esbuild/linux-ia32@0.25.0': optional: true + '@esbuild/linux-loong64@0.23.1': + optional: true + '@esbuild/linux-loong64@0.24.2': optional: true '@esbuild/linux-loong64@0.25.0': optional: true + '@esbuild/linux-mips64el@0.23.1': + optional: true + '@esbuild/linux-mips64el@0.24.2': optional: true '@esbuild/linux-mips64el@0.25.0': optional: true + '@esbuild/linux-ppc64@0.23.1': + optional: true + '@esbuild/linux-ppc64@0.24.2': optional: true '@esbuild/linux-ppc64@0.25.0': optional: true + '@esbuild/linux-riscv64@0.23.1': + optional: true + '@esbuild/linux-riscv64@0.24.2': optional: true '@esbuild/linux-riscv64@0.25.0': optional: true + '@esbuild/linux-s390x@0.23.1': + optional: true + '@esbuild/linux-s390x@0.24.2': optional: true '@esbuild/linux-s390x@0.25.0': optional: true + '@esbuild/linux-x64@0.23.1': + optional: true + '@esbuild/linux-x64@0.24.2': optional: true @@ -4870,42 +5222,63 @@ snapshots: '@esbuild/netbsd-arm64@0.25.0': optional: true + '@esbuild/netbsd-x64@0.23.1': + optional: true + '@esbuild/netbsd-x64@0.24.2': optional: true '@esbuild/netbsd-x64@0.25.0': optional: true + '@esbuild/openbsd-arm64@0.23.1': + optional: true + '@esbuild/openbsd-arm64@0.24.2': optional: true '@esbuild/openbsd-arm64@0.25.0': optional: true + '@esbuild/openbsd-x64@0.23.1': + optional: true + '@esbuild/openbsd-x64@0.24.2': optional: true '@esbuild/openbsd-x64@0.25.0': optional: true + '@esbuild/sunos-x64@0.23.1': + optional: true + '@esbuild/sunos-x64@0.24.2': optional: true '@esbuild/sunos-x64@0.25.0': optional: true + '@esbuild/win32-arm64@0.23.1': + optional: true + '@esbuild/win32-arm64@0.24.2': optional: true '@esbuild/win32-arm64@0.25.0': optional: true + '@esbuild/win32-ia32@0.23.1': + optional: true + '@esbuild/win32-ia32@0.24.2': optional: true '@esbuild/win32-ia32@0.25.0': optional: true + '@esbuild/win32-x64@0.23.1': + optional: true + '@esbuild/win32-x64@0.24.2': optional: true @@ -5312,13 +5685,13 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-vite@8.5.3(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0))': + '@storybook/builder-vite@8.5.3(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@storybook/csf-plugin': 8.5.3(storybook@8.5.3(prettier@3.4.2)) browser-assert: 1.2.1 storybook: 8.5.3(prettier@3.4.2) ts-dedent: 2.2.0 - vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) '@storybook/components@8.5.3(storybook@8.5.3(prettier@3.4.2))': dependencies: @@ -5382,9 +5755,9 @@ snapshots: dependencies: storybook: 8.5.3(prettier@3.4.2) - '@storybook/web-components-vite@8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0))': + '@storybook/web-components-vite@8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))': dependencies: - '@storybook/builder-vite': 8.5.3(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0)) + '@storybook/builder-vite': 8.5.3(storybook@8.5.3(prettier@3.4.2))(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) '@storybook/web-components': 8.5.3(lit@3.2.1)(storybook@8.5.3(prettier@3.4.2)) magic-string: 0.30.17 storybook: 8.5.3(prettier@3.4.2) @@ -5690,13 +6063,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.5(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0))': + '@vitest/mocker@3.0.5(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@vitest/spy': 3.0.5 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) '@vitest/pretty-format@3.0.5': dependencies: @@ -5951,6 +6324,8 @@ snapshots: dependencies: environment: 1.1.0 + ansi-regex@4.1.1: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -5965,6 +6340,11 @@ snapshots: ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -6097,6 +6477,10 @@ snapshots: dependencies: is-windows: 1.0.2 + binary-extensions@2.3.0: {} + + boolbase@1.0.0: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -6163,6 +6547,8 @@ snapshots: pascal-case: 3.1.2 tslib: 2.8.1 + camelcase@5.3.1: {} + camelcase@6.3.0: {} caniuse-lite@1.0.30001690: {} @@ -6200,6 +6586,25 @@ snapshots: check-error@2.1.1: {} + chokidar-cli@3.0.0: + dependencies: + chokidar: 3.5.2 + lodash.debounce: 4.0.8 + lodash.throttle: 4.1.1 + yargs: 13.3.2 + + chokidar@3.5.2: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chokidar@4.0.1: dependencies: readdirp: 4.0.2 @@ -6245,6 +6650,12 @@ snapshots: slice-ansi: 5.0.0 string-width: 7.2.0 + cliui@5.0.0: + dependencies: + string-width: 3.1.0 + strip-ansi: 5.2.0 + wrap-ansi: 5.1.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -6299,6 +6710,8 @@ snapshots: commander@2.20.3: {} + comment-parser@1.4.1: {} + commondir@1.0.1: {} concat-map@0.0.1: {} @@ -6339,11 +6752,21 @@ snapshots: css-functions-list@3.2.3: {} + css-select@5.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + css-tree@3.1.0: dependencies: mdn-data: 2.12.2 source-map-js: 1.2.1 + css-what@6.1.0: {} + cssesc@3.0.0: {} csstype@3.1.3: {} @@ -6384,6 +6807,8 @@ snapshots: dependencies: ms: 2.1.3 + decamelize@1.2.0: {} + deep-eql@5.0.2: {} deep-equal@1.0.1: {} @@ -6450,12 +6875,30 @@ snapshots: dependencies: esutils: 2.0.3 + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dom5@3.0.1: dependencies: '@types/parse5': 2.2.34 clone: 2.1.2 parse5: 4.0.0 + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -6483,6 +6926,8 @@ snapshots: emoji-regex@10.4.0: {} + emoji-regex@7.0.3: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -6600,6 +7045,34 @@ snapshots: transitivePeerDependencies: - supports-color + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + optional: true + esbuild@0.24.2: optionalDependencies: '@esbuild/aix-ppc64': 0.24.2 @@ -6949,6 +7422,10 @@ snapshots: dependencies: array-back: 3.1.0 + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -7066,6 +7543,11 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.7 + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + optional: true + get-uri@6.0.4: dependencies: basic-ftp: 5.0.5 @@ -7351,6 +7833,10 @@ snapshots: dependencies: has-bigints: 1.1.0 + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-boolean-object@1.2.1: dependencies: call-bound: 1.0.3 @@ -7389,6 +7875,8 @@ snapshots: dependencies: call-bound: 1.0.3 + is-fullwidth-code-point@2.0.0: {} + is-fullwidth-code-point@3.0.0: {} is-fullwidth-code-point@4.0.0: {} @@ -7689,6 +8177,11 @@ snapshots: lit-element: 4.1.1 lit-html: 3.2.1 + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -7699,6 +8192,8 @@ snapshots: lodash.camelcase@4.3.0: {} + lodash.debounce@4.0.8: {} + lodash.deburr@4.1.0: {} lodash.get@4.4.2: {} @@ -7707,6 +8202,8 @@ snapshots: lodash.startcase@4.4.0: {} + lodash.throttle@4.1.1: {} + lodash.truncate@4.4.2: {} lodash@4.17.21: {} @@ -7861,6 +8358,11 @@ snapshots: dependencies: whatwg-url: 5.0.0 + node-html-parser@7.0.1: + dependencies: + css-select: 5.1.0 + he: 1.2.0 + node-releases@2.0.19: {} normalize-package-data@2.5.0: @@ -7893,6 +8395,10 @@ snapshots: dependencies: path-key: 4.0.0 + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + object-inspect@1.13.3: {} object-keys@1.1.1: {} @@ -7993,6 +8499,10 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -8072,6 +8582,8 @@ snapshots: no-case: 3.0.4 tslib: 2.8.1 + path-exists@3.0.0: {} + path-exists@4.0.0: {} path-is-absolute@1.0.1: {} @@ -8267,6 +8779,10 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + readdirp@4.0.2: {} recast@0.23.9: @@ -8311,6 +8827,8 @@ snapshots: require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} + requireindex@1.2.0: {} requires-port@1.0.0: {} @@ -8324,6 +8842,9 @@ snapshots: http-errors: 1.6.3 path-is-absolute: 1.0.1 + resolve-pkg-maps@1.0.0: + optional: true + resolve@1.22.9: dependencies: is-core-module: 2.16.0 @@ -8442,6 +8963,8 @@ snapshots: semver@7.7.0: {} + set-blocking@2.0.0: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -8616,6 +9139,12 @@ snapshots: string-argv@0.3.2: {} + string-width@3.1.0: + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -8657,6 +9186,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -8861,6 +9394,14 @@ snapshots: tsscmp@1.0.6: {} + tsx@4.19.2: + dependencies: + esbuild: 0.23.1 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + optional: true + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -9007,13 +9548,13 @@ snapshots: vary@1.1.2: {} - vite-node@3.0.5(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0): + vite-node@3.0.5(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0): dependencies: cac: 6.7.14 debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 2.0.2 - vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' - jiti @@ -9028,7 +9569,7 @@ snapshots: - tsx - yaml - vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0): + vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0): dependencies: esbuild: 0.24.2 postcss: 8.5.1 @@ -9037,12 +9578,13 @@ snapshots: '@types/node': 22.10.2 fsevents: 2.3.3 terser: 5.37.0 + tsx: 4.19.2 yaml: 2.7.0 - vitest@3.0.5(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0): + vitest@3.0.5(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0): dependencies: '@vitest/expect': 3.0.5 - '@vitest/mocker': 3.0.5(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0)) + '@vitest/mocker': 3.0.5(vite@6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) '@vitest/pretty-format': 3.0.5 '@vitest/runner': 3.0.5 '@vitest/snapshot': 3.0.5 @@ -9058,8 +9600,8 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) - vite-node: 3.0.5(@types/node@22.10.2)(terser@5.37.0)(yaml@2.7.0) + vite: 6.0.11(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) + vite-node: 3.0.5(@types/node@22.10.2)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.10.2 @@ -9157,6 +9699,8 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 + which-module@2.0.1: {} + which-typed-array@1.1.18: dependencies: available-typed-arrays: 1.0.7 @@ -9187,6 +9731,12 @@ snapshots: wordwrapjs@5.1.0: {} + wrap-ansi@5.1.0: + dependencies: + ansi-styles: 3.2.1 + string-width: 3.1.0 + strip-ansi: 5.2.0 + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -9222,12 +9772,32 @@ snapshots: ws@8.18.0: {} + y18n@4.0.3: {} + y18n@5.0.8: {} yaml@2.7.0: {} + yargs-parser@13.1.2: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + yargs-parser@21.1.1: {} + yargs@13.3.2: + dependencies: + cliui: 5.0.0 + find-up: 3.0.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 3.1.0 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 13.1.2 + yargs@17.7.2: dependencies: cliui: 8.0.1 diff --git a/src/accordion.ts b/src/accordion.ts index ceafacfb4..e776e3e97 100644 --- a/src/accordion.ts +++ b/src/accordion.ts @@ -38,8 +38,11 @@ export default class GlideCoreAccordion extends LitElement { @required label?: string; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get open() { + get open(): boolean { return this.#isOpen; } @@ -47,9 +50,11 @@ export default class GlideCoreAccordion extends LitElement { const hasChanged = isOpen !== this.#isOpen; this.#isOpen = isOpen; - const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); + const isReducedMotion = window.matchMedia( + '(prefers-reduced-motion: reduce)', + ).matches; - if (reducedMotion.matches && hasChanged && this.#detailsElementRef.value) { + if (isReducedMotion && hasChanged && this.#detailsElementRef.value) { this.#detailsElementRef.value.open = isOpen; this.dispatchEvent( @@ -164,7 +169,12 @@ export default class GlideCoreAccordion extends LitElement { name="prefix-icon" @slotchange=${this.#onPrefixIconSlotChange} ${ref(this.#prefixIconSlotElementRef)} - > + > + + ${this.label} @@ -177,7 +187,12 @@ export default class GlideCoreAccordion extends LitElement { name="suffix-icons" @slotchange=${this.#onSuffixIconsSlotChange} ${ref(this.#suffixIconsSlotElementRef)} - > + > + + + > + + `; } diff --git a/src/button-group.button.ts b/src/button-group.button.ts index 01d73f53f..61bbce979 100644 --- a/src/button-group.button.ts +++ b/src/button-group.button.ts @@ -33,8 +33,11 @@ export default class GlideCoreButtonGroupButton extends LitElement { @required label?: string; + /** + * @default false + */ @property({ type: Boolean, reflect: true }) - get selected() { + get selected(): boolean { return this.#isSelected; } @@ -70,6 +73,14 @@ export default class GlideCoreButtonGroupButton extends LitElement { this.#componentElementRef.value?.focus(options); } + privateSelect() { + this.selected = true; + + this.dispatchEvent( + new Event('selected', { bubbles: true, composed: true }), + ); + } + override render() { return html`
+ > + +
+ > + +
`; @@ -139,11 +150,7 @@ export default class GlideCoreButtonGroup extends LitElement { // Guards against `button.selected` to prevent duplicate "change" and // "input" events. if (button && !button.disabled && !button.selected) { - button.selected = true; - - button.dispatchEvent( - new Event('selected', { bubbles: true, composed: true }), - ); + button.privateSelect(); } } } @@ -174,11 +181,7 @@ export default class GlideCoreButtonGroup extends LitElement { } if (previousButton instanceof GlideCoreButtonGroupButton) { - previousButton.selected = true; - - previousButton.dispatchEvent( - new Event('selected', { bubbles: true, composed: true }), - ); + previousButton.privateSelect(); } break; @@ -202,11 +205,7 @@ export default class GlideCoreButtonGroup extends LitElement { } if (nextButton instanceof GlideCoreButtonGroupButton) { - nextButton.selected = true; - - nextButton.dispatchEvent( - new Event('selected', { bubbles: true, composed: true }), - ); + nextButton.privateSelect(); } break; @@ -222,11 +221,7 @@ export default class GlideCoreButtonGroup extends LitElement { const button = event.target.closest('glide-core-button-group-button'); if (button && !button.disabled && !button.selected) { - button.selected = true; - - button.dispatchEvent( - new Event('selected', { bubbles: true, composed: true }), - ); + button.privateSelect(); } } diff --git a/src/button.ts b/src/button.ts index 7defb5b70..f72aee999 100644 --- a/src/button.ts +++ b/src/button.ts @@ -43,7 +43,8 @@ export default class GlideCoreButton extends LitElement { @property({ reflect: true }) size: 'large' | 'small' = 'large'; - @property({ reflect: true }) type: 'button' | 'submit' | 'reset' = 'button'; + @property({ reflect: true }) + type: 'button' | 'submit' | 'reset' = 'button'; @property({ reflect: true }) value = ''; @@ -53,7 +54,7 @@ export default class GlideCoreButton extends LitElement { @property({ reflect: true }) readonly version = packageJson.version; - get form() { + get form(): HTMLFormElement | null { return this.#internals.form; } @@ -81,7 +82,12 @@ export default class GlideCoreButton extends LitElement { name="prefix-icon" @slotchange=${this.#onPrefixIconSlotChange} ${ref(this.#prefixIconSlotElementRef)} - > + > + + ${this.label} @@ -89,7 +95,12 @@ export default class GlideCoreButton extends LitElement { name="suffix-icon" @slotchange=${this.#onSuffixIconSlotChange} ${ref(this.#suffixIconSlotElementRef)} - > + > + + `; } diff --git a/src/checkbox-group.styles.ts b/src/checkbox-group.styles.ts index 1192caa30..90f7b6096 100644 --- a/src/checkbox-group.styles.ts +++ b/src/checkbox-group.styles.ts @@ -26,7 +26,7 @@ export default [ } } - .checkboxes { + .default-slot { display: flex; flex-direction: column; grid-column: 2; diff --git a/src/checkbox-group.ts b/src/checkbox-group.ts index 8a33d90e0..cd16cef0a 100644 --- a/src/checkbox-group.ts +++ b/src/checkbox-group.ts @@ -46,8 +46,11 @@ export default class GlideCoreCheckboxGroup static override styles = styles; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get disabled() { + get disabled(): boolean { return this.#isDisabled; } @@ -76,8 +79,11 @@ export default class GlideCoreCheckboxGroup @property() privateSplit?: 'left' | 'middle'; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get required() { + get required(): boolean { return this.#isRequired; } @@ -108,8 +114,11 @@ export default class GlideCoreCheckboxGroup @property({ reflect: true }) tooltip?: string; + /** + * @default [] + */ @property({ reflect: true, type: Array }) - get value() { + get value(): string[] { return this.#value; } @@ -153,7 +162,7 @@ export default class GlideCoreCheckboxGroup @property({ reflect: true }) readonly version = packageJson.version; - checkValidity() { + checkValidity(): boolean { this.isCheckingValidity = true; const isValid = this.#internals.checkValidity(); this.isCheckingValidity = false; @@ -186,11 +195,11 @@ export default class GlideCoreCheckboxGroup } } - get form() { + get form(): HTMLFormElement | null { return this.#internals.form; } - get validity() { + get validity(): ValidityState { const isChecked = this.#checkboxes.some(({ checked }) => checked); if (this.required && !isChecked) { @@ -226,11 +235,11 @@ export default class GlideCoreCheckboxGroup checkbox?.focus(options); } - formAssociatedCallback() { + formAssociatedCallback(): void { this.form?.addEventListener('formdata', this.#onFormdata); } - formResetCallback() { + formResetCallback(): void { for (const checkbox of this.#checkboxes) { checkbox.formResetCallback(); } @@ -265,12 +274,17 @@ export default class GlideCoreCheckboxGroup })} > + > + +
@@ -282,7 +296,12 @@ export default class GlideCoreCheckboxGroup ), })} name="description" - > + > + + ${when( this.#isShowValidationFeedback && this.validityMessage, @@ -296,7 +315,7 @@ export default class GlideCoreCheckboxGroup
`; } - reportValidity() { + reportValidity(): boolean { this.isReportValidityOrSubmit = true; const isValid = this.#internals.reportValidity(); @@ -307,11 +326,11 @@ export default class GlideCoreCheckboxGroup return isValid; } - resetValidityFeedback() { + resetValidityFeedback(): void { this.isReportValidityOrSubmit = false; } - setCustomValidity(message: string) { + setCustomValidity(message: string): void { this.validityMessage = message; if (message === '') { @@ -334,7 +353,7 @@ export default class GlideCoreCheckboxGroup } } - setValidity(flags?: ValidityStateFlags, message?: string) { + setValidity(flags?: ValidityStateFlags, message?: string): void { this.validityMessage = message; // A validation message is required but unused because we disable native validation feedback. diff --git a/src/checkbox.styles.ts b/src/checkbox.styles.ts index 67f3a225c..65fd5d0bf 100644 --- a/src/checkbox.styles.ts +++ b/src/checkbox.styles.ts @@ -133,7 +133,7 @@ export default [ } .checked-icon { - --size: 0.75rem; + --private-size: 0.75rem; align-items: center; block-size: 100%; diff --git a/src/checkbox.ts b/src/checkbox.ts index 6a62e269a..3c8849fce 100644 --- a/src/checkbox.ts +++ b/src/checkbox.ts @@ -50,8 +50,8 @@ export default class GlideCoreCheckbox @property({ type: Boolean }) checked = false; - @property({ attribute: 'internally-inert', type: Boolean }) - internallyInert = false; + @property({ attribute: 'private-internally-inert', type: Boolean }) + privateInternallyInert = false; @property({ reflect: true, type: Boolean }) disabled = false; @@ -62,9 +62,12 @@ export default class GlideCoreCheckbox @property({ type: Boolean }) indeterminate = false; + /** + * @default undefined + */ @property({ reflect: true }) @required - get label() { + get label(): string | undefined { return this.#label; } @@ -111,7 +114,7 @@ export default class GlideCoreCheckbox // Private because it's only meant to be used by Dropdown. @property({ attribute: 'private-size' }) - privateSize: 'large' | 'small' = 'large'; + privateSize: 'small' | 'large' = 'large'; // Private because it's only meant to be used by Form Controls Layout. @property() @@ -130,8 +133,11 @@ export default class GlideCoreCheckbox @property({ reflect: true }) tooltip?: string; + /** + * @default undefined + */ @property({ reflect: true }) - get value() { + get value(): string { return this.#value; } @@ -161,11 +167,11 @@ export default class GlideCoreCheckbox @property({ reflect: true }) readonly version = packageJson.version; - get form() { + get form(): HTMLFormElement | null { return this.#internals.form; } - checkValidity() { + checkValidity(): boolean { this.isCheckingValidity = true; const isValid = this.#internals.checkValidity(); this.isCheckingValidity = false; @@ -200,7 +206,7 @@ export default class GlideCoreCheckbox this.#intersectionObserver?.disconnect(); } - get validity() { + get validity(): ValidityState { // If we're in a Checkbox Group, `disabled`, `required`, and whether or not // the form has been submitted don't apply because Checkbox Group handles those // states for the group as a whole. @@ -245,11 +251,11 @@ export default class GlideCoreCheckbox this.#inputElementRef.value?.focus(options); } - formAssociatedCallback() { + formAssociatedCallback(): void { this.form?.addEventListener('formdata', this.#onFormdata); } - formResetCallback() { + formResetCallback(): void { this.checked = this.getAttribute('checked') === ''; this.indeterminate = this.getAttribute('indeterminate') === ''; } @@ -273,7 +279,7 @@ export default class GlideCoreCheckbox data-test="input" type="checkbox" .checked=${this.checked} - .inert=${this.internallyInert} + .inert=${this.privateInternallyInert} ?disabled=${this.disabled} ?required=${this.required} @change=${this.#onInputChangeOrInput} @@ -294,7 +300,9 @@ export default class GlideCoreCheckbox
- + + + ${this.summary}
+ + > + + + ${when( this.#isShowValidationFeedback && this.validityMessage, () => @@ -395,7 +413,7 @@ export default class GlideCoreCheckbox
`; } - reportValidity() { + reportValidity(): boolean { this.privateIsReportValidityOrSubmit = true; const isValid = this.#internals.reportValidity(); @@ -405,11 +423,11 @@ export default class GlideCoreCheckbox return isValid; } - resetValidityFeedback() { + resetValidityFeedback(): void { this.privateIsReportValidityOrSubmit = false; } - setCustomValidity(message: string) { + setCustomValidity(message: string): void { this.validityMessage = message; if (message === '') { @@ -432,7 +450,7 @@ export default class GlideCoreCheckbox } } - setValidity(flags?: ValidityStateFlags, message?: string) { + setValidity(flags?: ValidityStateFlags, message?: string): void { this.validityMessage = message; this.#internals.setValidity(flags, ' ', this.#inputElementRef.value); } @@ -569,7 +587,7 @@ export default class GlideCoreCheckbox // Unlike "input" events, "change" events aren't composed. So we have to // manually dispatch them. this.dispatchEvent( - new Event(event.type, { bubbles: true, composed: true }), + new Event('change', { bubbles: true, composed: true }), ); } } diff --git a/src/drawer.styles.ts b/src/drawer.styles.ts index 9def92da5..d87ac049e 100644 --- a/src/drawer.styles.ts +++ b/src/drawer.styles.ts @@ -2,6 +2,11 @@ import { css } from 'lit'; export default [ css` + :host { + /* The width the drawer */ + --width: 27.375rem; + } + .component { background-color: var(--glide-core-surface-base-xlightest); block-size: 0; @@ -30,7 +35,7 @@ export default [ .open { backdrop-filter: blur(50px); block-size: auto; - inline-size: var(--width, 27.375rem); + inline-size: var(--width); inset: 0 0 0 auto; visibility: visible; } diff --git a/src/drawer.ts b/src/drawer.ts index 3b54d4bae..5c16963cd 100644 --- a/src/drawer.ts +++ b/src/drawer.ts @@ -40,8 +40,11 @@ export default class GlideCoreDrawer extends LitElement { @property({ reflect: true, type: Boolean }) pinned = false; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get open() { + get open(): boolean { return this.#isOpen; } @@ -166,7 +169,14 @@ export default class GlideCoreDrawer extends LitElement { tabindex="-1" ${ref(this.#componentElementRef)} > - + + + `; } diff --git a/src/dropdown.option.styles.ts b/src/dropdown.option.styles.ts index 7412e4f6e..f4db28f68 100644 --- a/src/dropdown.option.styles.ts +++ b/src/dropdown.option.styles.ts @@ -152,7 +152,7 @@ export default [ } .checked-icon-container { - --size: 1rem; + --private-size: 1rem; display: contents; diff --git a/src/dropdown.option.ts b/src/dropdown.option.ts index 2a9aa7afa..3f8aec931 100644 --- a/src/dropdown.option.ts +++ b/src/dropdown.option.ts @@ -35,8 +35,11 @@ export default class GlideCoreDropdownOption extends LitElement { static override styles = styles; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get disabled() { + get disabled(): boolean { return this.#isDisabled; } @@ -45,8 +48,11 @@ export default class GlideCoreDropdownOption extends LitElement { this.#isDisabled = isDisabled; } + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get editable() { + get editable(): boolean { return this.#isEditable; } @@ -60,9 +66,12 @@ export default class GlideCoreDropdownOption extends LitElement { ); } + /** + * @default undefined + */ @property({ reflect: true }) @required - get label() { + get label(): string | undefined { return this.#label; } @@ -95,8 +104,11 @@ export default class GlideCoreDropdownOption extends LitElement { @property({ attribute: 'private-multiple', type: Boolean }) privateMultiple = false; + /** + * @default false + */ @property({ reflect: true, type: Boolean }) - get selected() { + get selected(): boolean { return this.#selected; } @@ -206,8 +218,11 @@ export default class GlideCoreDropdownOption extends LitElement { } } + /** + * @default '' + */ @property({ reflect: true }) - get value() { + get value(): string { return this.#value; } @@ -229,6 +244,10 @@ export default class GlideCoreDropdownOption extends LitElement { this.#value = value; } + privateEdit() { + this.dispatchEvent(new Event('edit', { bubbles: true, composed: true })); + } + async privateUpdateCheckbox() { // Hacky indeed. This is for the case where Dropdown is set programmatically // from a single to a multiselect. `this.isMultiple` is set to `true` but @@ -246,7 +265,6 @@ export default class GlideCoreDropdownOption extends LitElement { // The linter wants a keyboard handler. There's one on Dropdown itself. It's there // because options aren't focusable and thus don't produce keyboard events when Dropdown // is filterable. - return html`
+ > + + ${when(this.editable, () => { @@ -323,7 +346,12 @@ export default class GlideCoreDropdownOption extends LitElement { + })} name="icon"> + + { return this.#optionElements.filter(({ label }) => { @@ -416,11 +436,11 @@ export default class GlideCoreDropdown } } - get form() { + get form(): HTMLFormElement | null { return this.#internals.form; } - get validity() { + get validity(): ValidityState { if (this.required && this.selectedOptions.length === 0) { // A validation message is required but unused because we disable native validation feedback. // And an empty string isn't allowed. Thus a single space. @@ -447,11 +467,11 @@ export default class GlideCoreDropdown return this.#internals.validity; } - formAssociatedCallback() { + formAssociatedCallback(): void { this.form?.addEventListener('formdata', this.#onFormdata); } - formResetCallback() { + formResetCallback(): void { for (const option of this.#optionElements) { const isInitiallySelected = option.hasAttribute('selected'); @@ -587,7 +607,15 @@ export default class GlideCoreDropdown data-test="multiselect-icon-slot" name="icon:${value}" slot="icon" - > + > + + `; })} @@ -604,7 +632,12 @@ export default class GlideCoreDropdown })} data-test="single-select-icon-slot" name="icon:${this.selectedOptions.at(0)?.value}" - >`; + > + + `; })} + > + +
${when(this.isNoResults, () => { @@ -880,7 +918,13 @@ export default class GlideCoreDropdown ), })} name="description" - > + > + + + ${when( this.#isShowValidationFeedback && this.validityMessage, () => @@ -893,9 +937,8 @@ export default class GlideCoreDropdown `; } - reportValidity() { + reportValidity(): boolean { this.isReportValidityOrSubmit = true; - const isValid = this.#internals.reportValidity(); // Ensures that getters referencing this.validity?.valid update (i.e. #isShowValidationFeedback) @@ -904,11 +947,11 @@ export default class GlideCoreDropdown return isValid; } - resetValidityFeedback() { + resetValidityFeedback(): void { this.isReportValidityOrSubmit = false; } - setCustomValidity(message: string) { + setCustomValidity(message: string): void { this.validityMessage = message; if (message === '') { @@ -935,7 +978,7 @@ export default class GlideCoreDropdown } } - setValidity(flags?: ValidityStateFlags, message?: string) { + setValidity(flags?: ValidityStateFlags, message?: string): void { this.validityMessage = message; // A validation message is required but unused because we disable native validation feedback. @@ -1430,9 +1473,7 @@ export default class GlideCoreDropdown // A "click" event, on the other hand, is dispatched when an Edit button is // clicked. So Dropdown Option could dispatch "edit" in that case. But then // two components instead of one would be responsible for dispatching "edit". - this.activeOption.dispatchEvent( - new Event('edit', { bubbles: true, composed: true }), - ); + this.activeOption.privateEdit(); this.open = false; @@ -1650,9 +1691,7 @@ export default class GlideCoreDropdown event.target instanceof Node && this.#editButtonElementRef.value?.contains(event.target) ) { - this.selectedOptions[0].dispatchEvent( - new Event('edit', { bubbles: true, composed: true }), - ); + this.selectedOptions[0].privateEdit(); return; } @@ -1939,10 +1978,7 @@ export default class GlideCoreDropdown option instanceof GlideCoreDropdownOption && option.privateIsEditActive ) { - option.dispatchEvent( - new Event('edit', { bubbles: true, composed: true }), - ); - + option.privateEdit(); this.open = false; return; @@ -2417,8 +2453,8 @@ const icons = { viewBox="0 0 16 16" fill="none" style=${styleMap({ - height: 'var(--size)', - width: 'var(--size)', + height: 'var(--private-size)', + width: 'var(--private-size)', })} > ( (name) => - `https://github.com/CrowdStrike/glide-core/blob/main/packages/eslint-plugin/src/rules/${name}.ts`, + `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`, ); export const consistentReferenceElementDeclarations = createRule({ diff --git a/src/eslint/rules/consistent-test-fixture-variable-declarator.ts b/src/eslint/rules/consistent-test-fixture-variable-declarator.ts index 138dab72c..1b5df289c 100644 --- a/src/eslint/rules/consistent-test-fixture-variable-declarator.ts +++ b/src/eslint/rules/consistent-test-fixture-variable-declarator.ts @@ -5,7 +5,7 @@ const createRule = ESLintUtils.RuleCreator<{ recommended: boolean; }>( (name) => - `https://github.com/CrowdStrike/glide-core/blob/main/packages/eslint-plugin/src/rules/${name}.ts`, + `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`, ); export const consistentTestFixtureVariableDeclarator = createRule({ @@ -27,7 +27,7 @@ export const consistentTestFixtureVariableDeclarator = createRule({ create(context) { return { VariableDeclarator(node) { - const isAFixture = + const isFixture = node.init && node.init.type === AST_NODE_TYPES.AwaitExpression && node.init.argument && @@ -37,7 +37,7 @@ export const consistentTestFixtureVariableDeclarator = createRule({ node.init.argument.callee.name === 'fixture' && node.init.argument.arguments?.length > 0; - if (!isAFixture) { + if (!isFixture) { return; } diff --git a/src/eslint/rules/event-dispatch-from-this.test.ts b/src/eslint/rules/event-dispatch-from-this.test.ts new file mode 100644 index 000000000..41f9ea5ee --- /dev/null +++ b/src/eslint/rules/event-dispatch-from-this.test.ts @@ -0,0 +1,48 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { eventDispatchFromThis } from './event-dispatch-from-this.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('event-dispatch-from-this', eventDispatchFromThis, { + valid: [ + { + code: ` + export default class { + method() { + this.dispatchEvent(new Event('change')) + } + } + `, + }, + ], + invalid: [ + { + code: ` + export default class { + method() { + this.element.dispatchEvent(new Event('change')) + } + } + `, + errors: [ + { + messageId: 'dispatchFromThis', + }, + ], + }, + { + code: ` + export default class { + method() { + document.querySelector('input').dispatchEvent(new Event('change')) + } + } + `, + errors: [ + { + messageId: 'dispatchFromThis', + }, + ], + }, + ], +}); diff --git a/src/eslint/rules/event-dispatch-from-this.ts b/src/eslint/rules/event-dispatch-from-this.ts new file mode 100644 index 000000000..5cfba2f1d --- /dev/null +++ b/src/eslint/rules/event-dispatch-from-this.ts @@ -0,0 +1,42 @@ +import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'; + +// https://github.com/typescript-eslint/typescript-eslint/blob/main/docs/developers/Custom_Rules.mdx?plain=1#L109 +const createRule = ESLintUtils.RuleCreator<{ + recommended: boolean; +}>((name) => { + return `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`; +}); + +export const eventDispatchFromThis = createRule({ + name: 'event-dispatch-from-this', + meta: { + docs: { + description: 'Ensures events are dispatched directly from `this`.', + recommended: true, + }, + type: 'suggestion', + messages: { + dispatchFromThis: + 'Dispatch events directly from `this` to help us populate our elements manifest with events.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + CallExpression(node) { + if ( + node.callee.type === AST_NODE_TYPES.MemberExpression && + node.callee.property.type === AST_NODE_TYPES.Identifier && + node.callee.property.name === 'dispatchEvent' && + node.callee.object.type !== AST_NODE_TYPES.ThisExpression + ) { + context.report({ + node, + messageId: 'dispatchFromThis', + }); + } + }, + }; + }, +}); diff --git a/src/eslint/rules/no-glide-core-prefixed-event-name.ts b/src/eslint/rules/no-glide-core-prefixed-event-name.ts index a0801ab68..9c13785c0 100644 --- a/src/eslint/rules/no-glide-core-prefixed-event-name.ts +++ b/src/eslint/rules/no-glide-core-prefixed-event-name.ts @@ -28,10 +28,12 @@ export const noPrefixedEventName = createRule({ create(context) { return { NewExpression(node) { - if ( + const isEvent = node.callee.type === AST_NODE_TYPES.Identifier && - (node.callee.name === 'Event' || - node.callee.name === 'CustomEvent') && + ['Event', 'CustomEvent'].includes(node.callee.name); + + if ( + isEvent && node.arguments.length > 0 && node.arguments[0].type === AST_NODE_TYPES.Literal && typeof node.arguments[0].value === 'string' && @@ -42,7 +44,7 @@ export const noPrefixedEventName = createRule({ context.report({ node, messageId: 'noPrefix', - fix: function (fixer) { + fix(fixer) { return fixer.replaceText( node.arguments[0], `'${eventName.replace('glide-core-', '')}'`, diff --git a/src/eslint/rules/no-redundant-property-attribute.ts b/src/eslint/rules/no-redundant-property-attribute.ts index 33c6b9df0..5517a4c92 100644 --- a/src/eslint/rules/no-redundant-property-attribute.ts +++ b/src/eslint/rules/no-redundant-property-attribute.ts @@ -87,7 +87,7 @@ export const noRedudantPropertyAttribute = createRule({ context.report({ node: property, messageId: 'noRedudantPropertyAttribute', - fix: function (fixer) { + fix(fixer) { if (argument.properties?.length === 1) { const source = context.sourceCode; const tokenBefore = source.getTokenBefore(argument); diff --git a/src/eslint/rules/no-redundant-property-string-type.ts b/src/eslint/rules/no-redundant-property-string-type.ts index 59c1019c3..858947b9b 100644 --- a/src/eslint/rules/no-redundant-property-string-type.ts +++ b/src/eslint/rules/no-redundant-property-string-type.ts @@ -69,7 +69,7 @@ export const noRedudantPropertyStringType = createRule({ context.report({ node: property, messageId: 'noRedudantPropertyStringType', - fix: function (fixer) { + fix(fixer) { if (argument.properties?.length === 1) { const source = context.sourceCode; const tokenBefore = source.getTokenBefore(argument); diff --git a/src/eslint/rules/no-space-press.ts b/src/eslint/rules/no-space-press.ts index ff6d6f0b1..4e46ec8ce 100644 --- a/src/eslint/rules/no-space-press.ts +++ b/src/eslint/rules/no-space-press.ts @@ -39,7 +39,7 @@ export const noSpacePress = createRule({ context.report({ node, messageId: 'preferWhitespace', - fix: function (fixer) { + fix(fixer) { return fixer.replaceText(node.right, "' '"); }, }); @@ -68,7 +68,7 @@ export const noSpacePress = createRule({ context.report({ node: property, messageId: 'preferWhitespace', - fix: function (fixer) { + fix(fixer) { return fixer.replaceText(property.value, "' '"); }, }); diff --git a/src/eslint/rules/prefer-to-be-true-or-false.ts b/src/eslint/rules/prefer-to-be-true-or-false.ts index 9d438c136..29a070682 100644 --- a/src/eslint/rules/prefer-to-be-true-or-false.ts +++ b/src/eslint/rules/prefer-to-be-true-or-false.ts @@ -50,7 +50,7 @@ export const preferToBeTrueOrFalse = createRule({ context.report({ node, messageId: 'preferToBeFalse', - fix: function (fixer) { + fix(fixer) { if (node.callee.type !== AST_NODE_TYPES.MemberExpression) { return null; } @@ -79,7 +79,7 @@ export const preferToBeTrueOrFalse = createRule({ context.report({ node, messageId: 'preferToBeTrue', - fix: function (fixer) { + fix(fixer) { if (node.callee.type !== AST_NODE_TYPES.MemberExpression) { return null; } diff --git a/src/eslint/rules/prefixed-lit-element-class-declaration.ts b/src/eslint/rules/prefixed-lit-element-class-declaration.ts index 42e4fcfc3..c08ac7c3b 100644 --- a/src/eslint/rules/prefixed-lit-element-class-declaration.ts +++ b/src/eslint/rules/prefixed-lit-element-class-declaration.ts @@ -37,7 +37,7 @@ export const prefixedClassDeclaration = createRule({ context.report({ node, messageId: 'addPrefix', - fix: function (fixer) { + fix(fixer) { const nodeId = node.id; if (!nodeId) { diff --git a/src/eslint/rules/public-getter-default-comment.test.ts b/src/eslint/rules/public-getter-default-comment.test.ts new file mode 100644 index 000000000..51e6ca8ee --- /dev/null +++ b/src/eslint/rules/public-getter-default-comment.test.ts @@ -0,0 +1,106 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { publicGetterDefaultComment } from './public-getter-default-comment.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('public-getter-default-comment', publicGetterDefaultComment, { + valid: [ + { + code: ` + export default class { + /** + * @default {string} + */ + get property() {} + set property() {} + } + `, + }, + { + code: ` + export default class { + get #property() {} + set #property() {} + } + `, + }, + { + code: ` + export default class { + private get property() {} + private set property() {} + } + `, + }, + { + code: ` + export default class { + get privateProperty() {} + set privateProperty() {} + } + `, + }, + { + code: ` + export default class { + override get property() {} + override set property() {} + } + `, + }, + { + code: ` + export default class { + override get property() {} + } + `, + }, + ], + invalid: [ + { + code: ` + export default class { + /** + * Description + */ + get property() {} + set property() {} + } + `, + errors: [ + { + messageId: 'addDefaultTag', + }, + ], + }, + { + code: ` + export default class { + get property() {} + set property() {} + } + `, + errors: [ + { + messageId: 'addCommentAndDefaultTag', + }, + ], + }, + { + code: ` + export default class { + /* + * @default {string} + */ + get property() {} + set property() {} + } + `, + errors: [ + { + messageId: 'useJsDocComment', + }, + ], + }, + ], +}); diff --git a/src/eslint/rules/public-getter-default-comment.ts b/src/eslint/rules/public-getter-default-comment.ts new file mode 100644 index 000000000..f73968e7f --- /dev/null +++ b/src/eslint/rules/public-getter-default-comment.ts @@ -0,0 +1,111 @@ +import { + AST_NODE_TYPES, + AST_TOKEN_TYPES, + ESLintUtils, +} from '@typescript-eslint/utils'; +import { parse as commentParser } from 'comment-parser'; + +// https://github.com/typescript-eslint/typescript-eslint/blob/main/docs/developers/Custom_Rules.mdx?plain=1#L109 +const createRule = ESLintUtils.RuleCreator<{ + recommended: boolean; +}>((name) => { + return `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`; +}); + +export const publicGetterDefaultComment = createRule({ + name: 'public-getter-default-comment', + meta: { + docs: { + description: + 'Ensures getters that have setters have a comment with `@default` tag.', + recommended: true, + }, + type: 'suggestion', + messages: { + addDefaultTag: + 'Add a "@default" tag to your comment help us populate our elements manifest with the correct default type.', + addCommentAndDefaultTag: + 'Add a JSDoc comment with a "@default" tag to help us populate our elements manifest with the correct default type.', + useJsDocComment: + 'Use a JSDoc-style comment to help us populate our elements manifest with the correct default type.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + const comments = context.sourceCode.getAllComments(); + + return { + MethodDefinition(node) { + const isPseudoPrivate = + node.key.type === AST_NODE_TYPES.Identifier && + node.key.name.startsWith('private'); + + const hasSetter = node.parent.body.some((classElement) => { + return ( + node.key.type === AST_NODE_TYPES.Identifier && + node.kind === 'get' && + classElement.type === AST_NODE_TYPES.MethodDefinition && + classElement.kind === 'set' && + classElement.key.type === AST_NODE_TYPES.Identifier && + classElement.key.name === node.key.name + ); + }); + + if ( + hasSetter && + node.kind === 'get' && + node.key.type !== AST_NODE_TYPES.PrivateIdentifier && + node.accessibility !== 'private' && + !isPseudoPrivate && + !node.override + ) { + const comment = comments.find(({ loc, type }) => { + return ( + type === AST_TOKEN_TYPES.Block && + loc.end.line === node.loc.start.line - 1 + ); + }); + + if (comment) { + const parsed = commentParser(`/** + ${comment.value} + */`); + + const hasDefaultTag = parsed.at(0)?.tags.some((tag) => { + return tag.tag === 'default'; + }); + + /* + * This is block comment. But it's not a JSDoc one. + */ + + /** + * This is a JSDoc one. + */ + if (hasDefaultTag && !comment.value.startsWith('*')) { + context.report({ + node, + messageId: 'useJsDocComment', + }); + } + + if (!hasDefaultTag) { + context.report({ + node, + messageId: 'addDefaultTag', + }); + } + + return; + } + + context.report({ + node, + messageId: 'addCommentAndDefaultTag', + }); + } + }, + }; + }, +}); diff --git a/src/eslint/rules/public-member-return-type.test.ts b/src/eslint/rules/public-member-return-type.test.ts new file mode 100644 index 000000000..c01274025 --- /dev/null +++ b/src/eslint/rules/public-member-return-type.test.ts @@ -0,0 +1,72 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { publicMemberReturnType } from './public-member-return-type.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('public-member-return-type', publicMemberReturnType, { + valid: [ + { + code: ` + export default class { + method(): boolean {} + } + `, + }, + { + code: ` + export default class { + #method() {} + } + `, + }, + { + code: ` + export default class { + private method() {} + } + `, + }, + { + code: ` + export default class { + privateMethod() {} + } + `, + }, + { + code: ` + export default class { + constructor() {} + } + `, + }, + { + code: ` + export default class { + override method() {} + } + `, + }, + { + code: ` + export default class { + set property() {} + } + `, + }, + ], + invalid: [ + { + code: ` + export default class { + method() {} + } + `, + errors: [ + { + messageId: 'addReturnType', + }, + ], + }, + ], +}); diff --git a/src/eslint/rules/public-member-return-type.ts b/src/eslint/rules/public-member-return-type.ts new file mode 100644 index 000000000..5c50fd07d --- /dev/null +++ b/src/eslint/rules/public-member-return-type.ts @@ -0,0 +1,50 @@ +import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'; + +// https://github.com/typescript-eslint/typescript-eslint/blob/main/docs/developers/Custom_Rules.mdx?plain=1#L109 +const createRule = ESLintUtils.RuleCreator<{ + recommended: boolean; +}>((name) => { + return `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`; +}); + +export const publicMemberReturnType = createRule({ + name: 'public-member-return-type', + meta: { + docs: { + description: + 'Ensures an explicit return type on public methods and getters with setters.', + recommended: true, + }, + type: 'suggestion', + messages: { + addReturnType: + 'Add an explicit return type to help us populate our elements manifest with the correct return type.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + MethodDefinition(node) { + const isPseudoPrivate = + node.key.type === AST_NODE_TYPES.Identifier && + node.key.name.startsWith('private'); + + if ( + node.kind !== 'constructor' && + node.kind !== 'set' && + node.key.type !== AST_NODE_TYPES.PrivateIdentifier && + node.accessibility !== 'private' && + !isPseudoPrivate && + !node.override && + !node.value.returnType + ) { + context.report({ + node, + messageId: 'addReturnType', + }); + } + }, + }; + }, +}); diff --git a/src/eslint/rules/slot-type-comment.test.ts b/src/eslint/rules/slot-type-comment.test.ts new file mode 100644 index 000000000..ad6ae474f --- /dev/null +++ b/src/eslint/rules/slot-type-comment.test.ts @@ -0,0 +1,77 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { slotTypeComment } from './slot-type-comment.js'; + +const ruleTester = new RuleTester(); +const classMap = () => null; + +ruleTester.run('slot-type-comment', slotTypeComment, { + valid: [ + { + code: ` + export default class { + render() { + return html\` + + + + \` + } + } + `, + }, + ], + invalid: [ + { + code: ` + export default class { + render() { + return html\` + + \` + } + } + `, + errors: [ + { + messageId: 'addSlotComment', + }, + ], + }, + { + code: ` + export default class { + render() { + return html\` + + + + \` + } + } + `, + errors: [ + { + messageId: 'addSlotTypeComment', + }, + ], + }, + { + code: ` + export default class { + render() { + return html\` + + + + \` + } + } + `, + errors: [ + { + messageId: 'addSlotTypeCommentType', + }, + ], + }, + ], +}); diff --git a/src/eslint/rules/slot-type-comment.ts b/src/eslint/rules/slot-type-comment.ts new file mode 100644 index 000000000..45aff2938 --- /dev/null +++ b/src/eslint/rules/slot-type-comment.ts @@ -0,0 +1,96 @@ +import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'; +import { parse as htmlParser, CommentNode } from 'node-html-parser'; +import { parse as commentParser } from 'comment-parser'; + +// https://github.com/typescript-eslint/typescript-eslint/blob/main/docs/developers/Custom_Rules.mdx?plain=1#L109 +const createRule = ESLintUtils.RuleCreator<{ + recommended: boolean; +}>((name) => { + return `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`; +}); + +export const slotTypeComment = createRule({ + name: 'slot-type-comment', + meta: { + docs: { + description: 'Ensures slots have a `@type` comment.', + recommended: true, + }, + type: 'suggestion', + messages: { + addSlotComment: + 'Add a comment inside your slot and include a `@type` tag.', + addSlotTypeComment: 'Add a `@type` tag to your slot comment.', + addSlotTypeCommentType: + "Add a type to your slot's `@type` tag. Check that the type is wrapped in curlies.", + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + TaggedTemplateExpression(node) { + if ( + node.tag.type === AST_NODE_TYPES.Identifier && + node.tag.name === 'html' + ) { + // Reducers are often inscrutable. But I thought this was a good case for + // one. + // + // A quasi is the string part of a template literal. When a template literal + // contains an expression, it's broken into a array of quasis, which we then + // have to recombine to get the entirety of the markup. + // + // eslint-disable-next-line unicorn/no-array-reduce + const markup = node.quasi.quasis.reduce((accumulator, quasi) => { + accumulator += quasi.value.raw; + return accumulator; + }, ''); + + const root = htmlParser(markup, { + comment: true, + }); + + for (const slot of root.querySelectorAll('slot')) { + const comment = slot.childNodes.find((node) => { + return node instanceof CommentNode; + }); + + if (!comment) { + context.report({ + node: node.quasi, + messageId: 'addSlotComment', + }); + + return; + } + + const tags = commentParser(`/** + ${comment.rawText} + */`).flatMap((block) => block.tags); + + const typeTag = tags.find((tag) => tag.tag === 'type'); + + if (!typeTag) { + context.report({ + node: node.quasi, + messageId: 'addSlotTypeComment', + }); + + return; + } + + if (typeTag.type === '') { + context.report({ + node: node.quasi, + messageId: 'addSlotTypeCommentType', + }); + + return; + } + } + } + }, + }; + }, +}); diff --git a/src/eslint/rules/string-event-name.test.ts b/src/eslint/rules/string-event-name.test.ts new file mode 100644 index 000000000..e87107055 --- /dev/null +++ b/src/eslint/rules/string-event-name.test.ts @@ -0,0 +1,43 @@ +import { RuleTester } from '@typescript-eslint/rule-tester'; +import { stringEventName } from './string-event-name.js'; + +const ruleTester = new RuleTester(); + +ruleTester.run('string-event-name', stringEventName, { + valid: [ + { + code: ` + this.dispatchEvent(new Event('change')); + `, + }, + { + code: ` + this.dispatchEvent(new CustomEvent('change')); + `, + }, + ], + invalid: [ + { + code: ` + const variable = 'change'; + this.dispatchEvent(new Event(variable)); + `, + errors: [ + { + messageId: 'stringEventName', + }, + ], + }, + { + code: ` + const variable = 'change'; + this.dispatchEvent(new CustomEvent(variable)); + `, + errors: [ + { + messageId: 'stringEventName', + }, + ], + }, + ], +}); diff --git a/src/eslint/rules/string-event-name.ts b/src/eslint/rules/string-event-name.ts new file mode 100644 index 000000000..3095209b9 --- /dev/null +++ b/src/eslint/rules/string-event-name.ts @@ -0,0 +1,44 @@ +import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'; + +// https://github.com/typescript-eslint/typescript-eslint/blob/main/docs/developers/Custom_Rules.mdx?plain=1#L109 +const createRule = ESLintUtils.RuleCreator<{ + recommended: boolean; +}>((name) => { + return `https://github.com/CrowdStrike/glide-core/blob/main/src/eslint/rules/${name}.ts`; +}); + +export const stringEventName = createRule({ + name: 'string-event-name', + meta: { + docs: { + description: 'Ensures events names are strings.', + recommended: true, + }, + type: 'suggestion', + messages: { + stringEventName: + 'Use a string for the event name to help us populate our elements manifest with events.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + NewExpression(node) { + const isRelevantConstructor = + node.callee.type === AST_NODE_TYPES.Identifier && + ['Event', 'CustomEvent'].includes(node.callee.name); + + if ( + isRelevantConstructor && + node.arguments.at(0)?.type !== AST_NODE_TYPES.Literal + ) { + context.report({ + node, + messageId: 'stringEventName', + }); + } + }, + }; + }, +}); diff --git a/src/form-controls-layout.ts b/src/form-controls-layout.ts index 93e0bb784..57488e5ed 100644 --- a/src/form-controls-layout.ts +++ b/src/form-controls-layout.ts @@ -32,8 +32,11 @@ export default class GlideCoreFormControlsLayout extends LitElement { static override styles = styles; + /** + * @default 'left' + */ @property({ reflect: true }) - get split() { + get split(): 'left' | 'middle' { return this.#split; } @@ -65,7 +68,9 @@ export default class GlideCoreFormControlsLayout extends LitElement { GlideCoreTextArea, ])} ${ref(this.#slotElementRef)} - > + > + + `; } diff --git a/src/icon-button.styles.ts b/src/icon-button.styles.ts index 3a9ddbeb3..ab3e12395 100644 --- a/src/icon-button.styles.ts +++ b/src/icon-button.styles.ts @@ -13,14 +13,14 @@ export default [ .component { align-items: center; - block-size: var(--size, 1.625rem); + block-size: var(--private-size, 1.625rem); border-color: transparent; border-radius: 0.5rem; border-style: solid; border-width: 1px; cursor: pointer; display: inline-flex; - inline-size: var(--size, 1.625rem); + inline-size: var(--private-size, 1.625rem); justify-content: center; padding-inline: 0; transition-duration: 150ms; @@ -39,7 +39,7 @@ export default [ &.primary { background-color: var(--glide-core-surface-primary); border-color: transparent; - color: var(--icon-color, var(--glide-core-icon-selected)); + color: var(--private-icon-color, var(--glide-core-icon-selected)); &:disabled { background-color: var(--glide-core-surface-base-gray-light); @@ -64,7 +64,7 @@ export default [ &.secondary { background-color: transparent; border-color: transparent; - color: var(--icon-color, var(--glide-core-icon-default)); + color: var(--private-icon-color, var(--glide-core-icon-default)); &:disabled { background-color: transparent; @@ -86,10 +86,10 @@ export default [ &.tertiary { background-color: transparent; - block-size: var(--size, 1rem); + block-size: var(--private-size, 1rem); border-color: transparent; - color: var(--icon-color, var(--glide-core-icon-default)); - inline-size: var(--size, 1rem); + color: var(--private-icon-color, var(--glide-core-icon-default)); + inline-size: var(--private-size, 1rem); padding: 0; &:focus-visible { @@ -106,7 +106,7 @@ export default [ &:not(:active):hover:not(:disabled) { color: var( - --hovered-icon-color, + --private-hovered-icon-color, var(--glide-core-icon-primary-hover) ); } diff --git a/src/icon-button.ts b/src/icon-button.ts index 57aa5961a..f4b4d9c36 100644 --- a/src/icon-button.ts +++ b/src/icon-button.ts @@ -81,7 +81,13 @@ export default class GlideCoreIconButton extends LitElement { ?disabled=${this.disabled} ${ref(this.#buttonElementRef)} > - + + + `; } diff --git a/src/icons/checked.ts b/src/icons/checked.ts index 573b0609c..3d39bfc1f 100644 --- a/src/icons/checked.ts +++ b/src/icons/checked.ts @@ -12,8 +12,8 @@ export default html` fill="none" viewBox="0 0 24 24" style=${styleMap({ - height: 'var(--size, 0.875rem)', - width: 'var(--size, 0.875rem)', + height: 'var(--private-size, 0.875rem)', + width: 'var(--private-size, 0.875rem)', })} >