diff --git a/.changeset/gold-things-relate.md b/.changeset/gold-things-relate.md new file mode 100644 index 000000000..2bc0df0e7 --- /dev/null +++ b/.changeset/gold-things-relate.md @@ -0,0 +1,8 @@ +--- +"@bento/environment": major +"@bento/use-props": major +"@bento/slots": major +"@bento/box": major +--- + +data-override attributes are now opt-in using the Environment component diff --git a/.cursor/worktrees.json b/.cursor/worktrees.json new file mode 100644 index 000000000..77e9744d2 --- /dev/null +++ b/.cursor/worktrees.json @@ -0,0 +1,5 @@ +{ + "setup-worktree": [ + "npm install" + ] +} diff --git a/apps/docs/.storybook/main.ts b/apps/docs/.storybook/main.ts index 7c3d1a7a2..732d92ed2 100644 --- a/apps/docs/.storybook/main.ts +++ b/apps/docs/.storybook/main.ts @@ -4,7 +4,6 @@ import { createRequire } from 'node:module'; import { fileURLToPath } from 'node:url'; import { dirname, join, resolve } from 'node:path'; import { mergeConfig } from 'vite'; -import packageJson from '@bento/internal-props/package.json' with { type: 'json' }; const __dirname = dirname(fileURLToPath(import.meta.url)); const require = createRequire(import.meta.url); @@ -61,23 +60,10 @@ const config: StorybookConfig = { }, async viteFinal(config) { - const versionMatch = packageJson.version.match(/^(\d+)\.(\d+)\.(\d+)/); - const semver = versionMatch ? versionMatch.slice(1) : ['0', '0', '0']; - - const define = { - major: semver[0], - minor: semver[1], - patch: semver[2] - }; - return mergeConfig(config, { // Set envDir to workspace root for proper monorepo support envDir: resolve(__dirname, '../../../'), - esbuild: { - define - }, - // Exclude @bento packages from optimization so they can be watched and hot-reloaded optimizeDeps: { exclude: ['@bento/*'] diff --git a/apps/docs/package.json b/apps/docs/package.json index 817016de1..d931fc292 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -26,7 +26,6 @@ "@bento/icon": "*", "@bento/illustration": "*", "@bento/input": "*", - "@bento/internal-props": "*", "@bento/listbox": "*", "@bento/overlay": "*", "@bento/portal": "*", diff --git a/knip.config.ts b/knip.config.ts index 17c2a9537..d53643aae 100644 --- a/knip.config.ts +++ b/knip.config.ts @@ -26,7 +26,8 @@ const config: KnipConfig = { // Ignore circular dependencies in examples and tests - these are for demo purposes ignore: [ 'examples/**/*', // Example files that may use circular dependencies for demos - 'test/**/*.test.tsx' // Test files that may need circular dependencies for testing + 'test/**/*.test.tsx', // Test files that may need circular dependencies for testing + 'test/**/*.test.ts' // Test files that may need circular dependencies for testing ] }, 'packages/storybook-addon-helpers': { diff --git a/package-lock.json b/package-lock.json index e259680e0..0b7ca99ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,6 @@ "@bento/icon": "*", "@bento/illustration": "*", "@bento/input": "*", - "@bento/internal-props": "*", "@bento/listbox": "*", "@bento/overlay": "*", "@bento/portal": "*", @@ -148,9 +147,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "dev": true, "license": "MIT", "engines": { @@ -508,10 +507,6 @@ "resolved": "packages/input", "link": true }, - "node_modules/@bento/internal-props": { - "resolved": "packages/internal-props", - "link": true - }, "node_modules/@bento/listbox": { "resolved": "packages/listbox", "link": true @@ -740,13 +735,13 @@ } }, "node_modules/@changesets/apply-release-plan": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.14.tgz", - "integrity": "sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.13.tgz", + "integrity": "sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==", "dev": true, "license": "MIT", "dependencies": { - "@changesets/config": "^3.1.2", + "@changesets/config": "^3.1.1", "@changesets/get-version-range-type": "^0.4.0", "@changesets/git": "^3.0.4", "@changesets/should-skip-package": "^0.1.2", @@ -787,27 +782,27 @@ } }, "node_modules/@changesets/cli": { - "version": "2.29.8", - "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.8.tgz", - "integrity": "sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==", + "version": "2.29.7", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.29.7.tgz", + "integrity": "sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==", "dev": true, "license": "MIT", "dependencies": { - "@changesets/apply-release-plan": "^7.0.14", + "@changesets/apply-release-plan": "^7.0.13", "@changesets/assemble-release-plan": "^6.0.9", "@changesets/changelog-git": "^0.2.1", - "@changesets/config": "^3.1.2", + "@changesets/config": "^3.1.1", "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.3", - "@changesets/get-release-plan": "^4.0.14", + "@changesets/get-release-plan": "^4.0.13", "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.6", + "@changesets/read": "^0.6.5", "@changesets/should-skip-package": "^0.1.2", "@changesets/types": "^6.1.0", "@changesets/write": "^0.4.0", - "@inquirer/external-editor": "^1.0.2", + "@inquirer/external-editor": "^1.0.0", "@manypkg/get-packages": "^1.1.3", "ansi-colors": "^4.1.3", "ci-info": "^3.7.0", @@ -827,9 +822,9 @@ } }, "node_modules/@changesets/config": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.2.tgz", - "integrity": "sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.1.tgz", + "integrity": "sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==", "dev": true, "license": "MIT", "dependencies": { @@ -877,16 +872,16 @@ } }, "node_modules/@changesets/get-release-plan": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.14.tgz", - "integrity": "sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.13.tgz", + "integrity": "sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==", "dev": true, "license": "MIT", "dependencies": { "@changesets/assemble-release-plan": "^6.0.9", - "@changesets/config": "^3.1.2", + "@changesets/config": "^3.1.1", "@changesets/pre": "^2.0.2", - "@changesets/read": "^0.6.6", + "@changesets/read": "^0.6.5", "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" } @@ -923,14 +918,14 @@ } }, "node_modules/@changesets/parse": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.2.tgz", - "integrity": "sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.1.tgz", + "integrity": "sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==", "dev": true, "license": "MIT", "dependencies": { "@changesets/types": "^6.1.0", - "js-yaml": "^4.1.1" + "js-yaml": "^3.13.1" } }, "node_modules/@changesets/pre": { @@ -947,15 +942,15 @@ } }, "node_modules/@changesets/read": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.6.tgz", - "integrity": "sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.5.tgz", + "integrity": "sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==", "dev": true, "license": "MIT", "dependencies": { "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", - "@changesets/parse": "^0.4.2", + "@changesets/parse": "^0.4.1", "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", "p-filter": "^2.1.0", @@ -1306,18 +1301,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@emotion/babel-plugin/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1819,9 +1802,9 @@ } }, "node_modules/@formatjs/ecma402-abstract": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz", - "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.5.tgz", + "integrity": "sha512-1HTESOq1IUa23g1lFZEGIXsfZKZOwWmB9RROwGn+xariiQnd++wwTMvlRAbZ8wtXRHFUamJPxsKcxpSzeCvFWQ==", "license": "MIT", "dependencies": { "@formatjs/fast-memoize": "2.2.7", @@ -1840,23 +1823,23 @@ } }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz", - "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.3.tgz", + "integrity": "sha512-H/KfWSosaiDiOaW4nHe1Fn4Cgzm+oFQ8giTmB5RJzTBNSMmd+j2NVrvvZHAmlxJHcuOelzKBLjQ2EDcyH4NSWw==", "license": "MIT", "dependencies": { - "@formatjs/ecma402-abstract": "2.3.6", - "@formatjs/icu-skeleton-parser": "1.8.16", + "@formatjs/ecma402-abstract": "2.3.5", + "@formatjs/icu-skeleton-parser": "1.8.15", "tslib": "^2.8.0" } }, "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.16", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz", - "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==", + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.15.tgz", + "integrity": "sha512-qNrKxWJmnWxin5U4A4Evy7C0rgRiNw3IqXu9OGuT31B8lDxBGl+OgT8kcq0ZVKK0gqA4l4SQB9x+SFAvLT5hcQ==", "license": "MIT", "dependencies": { - "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/ecma402-abstract": "2.3.5", "tslib": "^2.8.0" } }, @@ -1870,13 +1853,13 @@ } }, "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.2.tgz", + "integrity": "sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==", "dev": true, "license": "MIT", "dependencies": { - "chardet": "^2.1.1", + "chardet": "^2.1.0", "iconv-lite": "^0.7.0" }, "engines": { @@ -2286,6 +2269,16 @@ "@rushstack/node-core-library": "5.19.1" } }, + "node_modules/@microsoft/api-extractor/node_modules/diff": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", + "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/@microsoft/api-extractor/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2564,9 +2557,9 @@ ] }, "node_modules/@oxc-resolver/binding-android-arm-eabi": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.15.0.tgz", - "integrity": "sha512-Q+lWuFfq7whNelNJIP1dhXaVz4zO9Tu77GcQHyxDWh3MaCoO2Bisphgzmsh4ZoUe2zIchQh6OvQL99GlWHg9Tw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.16.0.tgz", + "integrity": "sha512-/kFX4o8KISHCZzHRs8fBp/wZOPdkhYGquhMP2PQjc8ePAVbtaXXDPAFkjUKhz2jXNPS4jGA1wNW+8grhnJgstw==", "cpu": [ "arm" ], @@ -2578,9 +2571,9 @@ ] }, "node_modules/@oxc-resolver/binding-android-arm64": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.15.0.tgz", - "integrity": "sha512-vbdBttesHR0W1oJaxgWVTboyMUuu+VnPsHXJ6jrXf4czELzB6GIg5DrmlyhAmFBhjwov+yJH/DfTnHS+2sDgOw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.16.0.tgz", + "integrity": "sha512-kPySx7j7mPxW4mRDrdbADyzJV2XrxVeMPDmNnFvTt0/LT1IA26Uk9hzWKQb4k4aeJY58bnRY1soYSawW5wAlKQ==", "cpu": [ "arm64" ], @@ -2592,9 +2585,9 @@ ] }, "node_modules/@oxc-resolver/binding-darwin-arm64": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.15.0.tgz", - "integrity": "sha512-R67lsOe1UzNjqVBCwCZX1rlItTsj/cVtBw4Uy19CvTicqEWvwaTn8t34zLD75LQwDDPCY3C8n7NbD+LIdw+ZoA==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.16.0.tgz", + "integrity": "sha512-eB00fkys5TX6oI3lY+1hgHl6dwfmrbhHTmInmJmfD6BysHpE+DUqSdQIRS2v5NI6+j+J9EWBmbW3hRtolr+MSg==", "cpu": [ "arm64" ], @@ -2606,9 +2599,9 @@ ] }, "node_modules/@oxc-resolver/binding-darwin-x64": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.15.0.tgz", - "integrity": "sha512-77mya5F8WV0EtCxI0MlVZcqkYlaQpfNwl/tZlfg4jRsoLpFbaTeWv75hFm6TE84WULVlJtSgvf7DhoWBxp9+ZQ==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.16.0.tgz", + "integrity": "sha512-B/yMSxqe4MZfh/VoMax0qixl4XxG/sAQVlYtdVGNteBAYKfX/uw2mglkYsApk6D4qD6fVgJ21RwI50lV7oD0Qg==", "cpu": [ "x64" ], @@ -2620,9 +2613,9 @@ ] }, "node_modules/@oxc-resolver/binding-freebsd-x64": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.15.0.tgz", - "integrity": "sha512-X1Sz7m5PC+6D3KWIDXMUtux+0Imj6HfHGdBStSvgdI60OravzI1t83eyn6eN0LPTrynuPrUgjk7tOnOsBzSWHw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.16.0.tgz", + "integrity": "sha512-aKj+PNsSdn0owueMt/6TtR8QuLBNL/q2HgMdN8nRCDmoCBPvQlwB2s+AcW+UW1vyiok+9qiI5tVjihbKwQ+Khg==", "cpu": [ "x64" ], @@ -2634,9 +2627,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.15.0.tgz", - "integrity": "sha512-L1x/wCaIRre+18I4cH/lTqSAymlV0k4HqfSYNNuI9oeL28Ks86lI6O5VfYL6sxxWYgjuWB98gNGo7tq7d4GarQ==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.16.0.tgz", + "integrity": "sha512-fxod0D0eMsIlGF98KRAwR3zjLCbpRoknDHjCHx22A9TmyQthGo7t66gwkRCj5g2LBbpaPZ+i6cYd2l9bRrx8+Q==", "cpu": [ "arm" ], @@ -2648,9 +2641,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.15.0.tgz", - "integrity": "sha512-abGXd/zMGa0tH8nKlAXdOnRy4G7jZmkU0J85kMKWns161bxIgGn/j7zxqh3DKEW98wAzzU9GofZMJ0P5YCVPVw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.16.0.tgz", + "integrity": "sha512-5BoVnD0hpEID/13hnj0fCIojE26wfa9p4puCnm12/D5BhGlXA103n8iRaPZPLHS/prQGtrwMiFONiysD6vmIBA==", "cpu": [ "arm" ], @@ -2662,9 +2655,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.15.0.tgz", - "integrity": "sha512-SVjjjtMW66Mza76PBGJLqB0KKyFTBnxmtDXLJPbL6ZPGSctcXVmujz7/WAc0rb9m2oV0cHQTtVjnq6orQnI/jg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.16.0.tgz", + "integrity": "sha512-dMoKX6A8iuIdShbc4PB/+q6Tx8grgQxNAJQfIAmpaDTZp5NxfgzKrssPL0TCdu3RQMblF8yfXLYUFnOdPYZeRg==", "cpu": [ "arm64" ], @@ -2676,9 +2669,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm64-musl": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.15.0.tgz", - "integrity": "sha512-JDv2/AycPF2qgzEiDeMJCcSzKNDm3KxNg0KKWipoKEMDFqfM7LxNwwSVyAOGmrYlE4l3dg290hOMsr9xG7jv9g==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.16.0.tgz", + "integrity": "sha512-oLJsyqVHw53ZZPl3+wPiRNXTvavBFSInRYBB5MaNf+y42+b4XJfH7hVYyc67er0c26cQUCfx2KzqltSx7Jg9jg==", "cpu": [ "arm64" ], @@ -2690,9 +2683,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.15.0.tgz", - "integrity": "sha512-zbu9FhvBLW4KJxo7ElFvZWbSt4vP685Qc/Gyk/Ns3g2gR9qh2qWXouH8PWySy+Ko/qJ42+HJCLg+ZNcxikERfg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.16.0.tgz", + "integrity": "sha512-qL7GsXwyytVTIh/o8cLftRYvzrpniD8pFf0jDW3VXlVsl1joCrb4GM26udGls7Zxe76nsZpPvQVB5eZ9xmHxIA==", "cpu": [ "ppc64" ], @@ -2704,9 +2697,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.15.0.tgz", - "integrity": "sha512-Kfleehe6B09C2qCnyIU01xLFqFXCHI4ylzkicfX/89j+gNHh9xyNdpEvit88Kq6i5tTGdavVnM6DQfOE2qNtlg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.16.0.tgz", + "integrity": "sha512-CFJEvagoakxPtIoKtRgPoGUqeXSgd63c3/T9hOXrgelOaMv6aEWFfjvc/4Lk5ppk2wv4KeK4IqOKBe8Faqv1Mw==", "cpu": [ "riscv64" ], @@ -2718,9 +2711,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-riscv64-musl": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.15.0.tgz", - "integrity": "sha512-J7LPiEt27Tpm8P+qURDwNc8q45+n+mWgyys4/V6r5A8v5gDentHRGUx3iVk5NxdKhgoGulrzQocPTZVosq25Eg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.16.0.tgz", + "integrity": "sha512-LVuE2tbZ7gjEjY1G8mjf7+pacj0/Rge9EoHxr8DY2gAxxy0qXe5Yh2Qxe3dwwFGObVNioqRH0IPkePmQ/KJK6w==", "cpu": [ "riscv64" ], @@ -2732,9 +2725,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.15.0.tgz", - "integrity": "sha512-+8/d2tAScPjVJNyqa7GPGnqleTB/XW9dZJQ2D/oIM3wpH3TG+DaFEXBbk4QFJ9K9AUGBhvQvWU2mQyhK/yYn3Q==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.16.0.tgz", + "integrity": "sha512-D4Zk48WN7sKsbyq4xD2F09U4S0sIkHXTW9A33BaqjfNXOD/jFXM5nTPahHx2RxBLo5ZEgS3kUW1U8V0oCBcPcg==", "cpu": [ "s390x" ], @@ -2746,9 +2739,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-x64-gnu": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.15.0.tgz", - "integrity": "sha512-xtvSzH7Nr5MCZI2FKImmOdTl9kzuQ51RPyLh451tvD2qnkg3BaqI9Ox78bTk57YJhlXPuxWSOL5aZhKAc9J6qg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.16.0.tgz", + "integrity": "sha512-WyqsQwz+x1lDe/rwf5pl/FiTiS4eEM7hEHn1OwjP+EThzXXBup9BeZE5QVB421QGm9n4SyJT1gJgI1LCRvqbaA==", "cpu": [ "x64" ], @@ -2760,9 +2753,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-x64-musl": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.15.0.tgz", - "integrity": "sha512-14YL1zuXj06+/tqsuUZuzL0T425WA/I4nSVN1kBXeC5WHxem6lQ+2HGvG+crjeJEqHgZUT62YIgj88W+8E7eyg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.16.0.tgz", + "integrity": "sha512-5XCuIoviaMsiAAuaQL4HqnYj1BkADcbtdf2s6Ru4YHF3P/bt2p05hd4xVo85cFT1VXlGYL66XVfepsAGymJs0g==", "cpu": [ "x64" ], @@ -2774,9 +2767,9 @@ ] }, "node_modules/@oxc-resolver/binding-openharmony-arm64": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.15.0.tgz", - "integrity": "sha512-/7Qli+1Wk93coxnrQaU8ySlICYN8HsgyIrzqjgIkQEpI//9eUeaeIHZptNl2fMvBGeXa7k2QgLbRNaBRgpnvMw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.16.0.tgz", + "integrity": "sha512-gn54HKxOhWTxZG8pNeBMmbRwHT4k/eIf0KxBII2oHUrSTinNTcqu6xn1etqt1Yezi9KzJzkTMS0cl5kTFmCHUQ==", "cpu": [ "arm64" ], @@ -2788,9 +2781,9 @@ ] }, "node_modules/@oxc-resolver/binding-wasm32-wasi": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.15.0.tgz", - "integrity": "sha512-q5rn2eIMQLuc/AVGR2rQKb2EVlgreATGG8xXg8f4XbbYCVgpxaq+dgMbiPStyNywW1MH8VU2T09UEm30UtOQvg==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.16.0.tgz", + "integrity": "sha512-dUsUjffSI7nlt+TH9C4gGqmD/kNyx3Kghh8u+i8eZZAEFWDO+s51Yw3UADDa0BYrZDeaLjz8rgHWCE8lxpL2XQ==", "cpu": [ "wasm32" ], @@ -2829,9 +2822,9 @@ } }, "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.15.0.tgz", - "integrity": "sha512-yCAh2RWjU/8wWTxQDgGPgzV9QBv0/Ojb5ej1c/58iOjyTuy/J1ZQtYi2SpULjKmwIxLJdTiCHpMilauWimE31w==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.16.0.tgz", + "integrity": "sha512-6EhsnwzA6iT752sU5tv/r+XI5cz6sWUPHJZu3brTW3m96j6yCZ8vnfeKAkFCzuDwZAXOkRLPW8WKrL0GXWfCUQ==", "cpu": [ "arm64" ], @@ -2843,9 +2836,9 @@ ] }, "node_modules/@oxc-resolver/binding-win32-ia32-msvc": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.15.0.tgz", - "integrity": "sha512-lmXKb6lvA6M6QIbtYfgjd+AryJqExZVSY2bfECC18OPu7Lv1mHFF171Mai5l9hG3r4IhHPPIwT10EHoilSCYeA==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.16.0.tgz", + "integrity": "sha512-YpUXuKrslGs4+In1gZhY25menhzyBbMct4RvWT9je6mYA5VCQ6aGAZf/ky5b+5sNPpR2UBNbCcYk5pP/6MowMw==", "cpu": [ "ia32" ], @@ -2857,9 +2850,9 @@ ] }, "node_modules/@oxc-resolver/binding-win32-x64-msvc": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.15.0.tgz", - "integrity": "sha512-HZsfne0s/tGOcJK9ZdTGxsNU2P/dH0Shf0jqrPvsC6wX0Wk+6AyhSpHFLQCnLOuFQiHHU0ePfM8iYsoJb5hHpQ==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.16.0.tgz", + "integrity": "sha512-x3hU0m0c/+frUSFaw3r5Xmde5q/PdsAfznh+8lZloGK2/qfIze0jyQG0H5M6AgrUIQE1oNn8vdGXanza5+naMw==", "cpu": [ "x64" ], @@ -2882,15 +2875,15 @@ } }, "node_modules/@playwright/experimental-ct-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/@playwright/experimental-ct-core/-/experimental-ct-core-1.57.0.tgz", - "integrity": "sha512-Z5Uh+61vR5FDRE+YJIMrnD8m6i2wJmYK525AHCJNcAcGcEC+i7xuMnZmZkg+booi3YHIwql/ApAlm03+jsCIzQ==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/experimental-ct-core/-/experimental-ct-core-1.56.1.tgz", + "integrity": "sha512-xonl51bJxQpX4O5awQZlUJ4eMdu6WE6xdALz8VeJmWL04A6xZICXAOHu03msFqYRydbW0vvTfp5zaeHLsXoiSA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.57.0", - "playwright-core": "1.57.0", - "vite": "^6.4.1" + "playwright": "1.56.1", + "playwright-core": "1.56.1", + "vite": "^6.3.6" }, "engines": { "node": ">=18" @@ -3471,13 +3464,13 @@ } }, "node_modules/@playwright/experimental-ct-react": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/@playwright/experimental-ct-react/-/experimental-ct-react-1.57.0.tgz", - "integrity": "sha512-wNRmkLOxHEXA9OL7QggNYVHnqaGlMOTB5q9FhrnlcFHHRs+M8SH9mQy5//dGFoYKAkhuZf4GPA3poi9bBdkdfQ==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/experimental-ct-react/-/experimental-ct-react-1.56.1.tgz", + "integrity": "sha512-1L0AxZ5f7ekd7uKF8kDY1eu90MTBRMdYlZVUSgVydBqKUQhlwJuQTzZLoh6e8JWnHECH/5Rkq+uWPfa0ab9TsQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.57.0", + "@playwright/experimental-ct-core": "1.56.1", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -3515,16 +3508,6 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@playwright/experimental-ct-react/node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -5357,9 +5340,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", + "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", "cpu": [ "arm" ], @@ -5371,9 +5354,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", + "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", "cpu": [ "arm64" ], @@ -5385,9 +5368,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", + "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", "cpu": [ "arm64" ], @@ -5399,9 +5382,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", + "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", "cpu": [ "x64" ], @@ -5413,9 +5396,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", + "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", "cpu": [ "arm64" ], @@ -5427,9 +5410,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", + "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", "cpu": [ "x64" ], @@ -5441,9 +5424,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", + "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", "cpu": [ "arm" ], @@ -5455,9 +5438,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", + "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", "cpu": [ "arm" ], @@ -5469,9 +5452,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", + "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", "cpu": [ "arm64" ], @@ -5483,9 +5466,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", + "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", "cpu": [ "arm64" ], @@ -5497,9 +5480,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", + "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", "cpu": [ "loong64" ], @@ -5511,9 +5494,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", + "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", "cpu": [ "ppc64" ], @@ -5525,9 +5508,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", + "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", "cpu": [ "riscv64" ], @@ -5539,9 +5522,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", + "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", "cpu": [ "riscv64" ], @@ -5553,9 +5536,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", + "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", "cpu": [ "s390x" ], @@ -5567,9 +5550,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", + "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", "cpu": [ "x64" ], @@ -5581,9 +5564,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", + "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", "cpu": [ "x64" ], @@ -5595,9 +5578,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", + "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", "cpu": [ "arm64" ], @@ -5609,9 +5592,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", + "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", "cpu": [ "arm64" ], @@ -5623,9 +5606,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", + "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", "cpu": [ "ia32" ], @@ -5637,9 +5620,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", + "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", "cpu": [ "x64" ], @@ -5651,9 +5634,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", + "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", "cpu": [ "x64" ], @@ -5867,16 +5850,16 @@ "license": "MIT" }, "node_modules/@storybook/addon-docs": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.16.tgz", - "integrity": "sha512-JfaUD6fC7ySLg5duRdaWZ0FUUXrgUvqbZe/agCbSyOaIHOtJdhGaPjOC3vuXTAcV8/8/wWmbu0iXFMD08iKvdw==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-9.1.15.tgz", + "integrity": "sha512-thbBQKzN0ycSEQjtIeXJT4i6+4kWoNIWYo4x2GQ3jtqHsT8T4FZW1n/xK1ysZbB4eCwG2hOn44BRTu8p4S7UoQ==", "dev": true, "license": "MIT", "dependencies": { "@mdx-js/react": "^3.0.0", - "@storybook/csf-plugin": "9.1.16", + "@storybook/csf-plugin": "9.1.15", "@storybook/icons": "^1.4.0", - "@storybook/react-dom-shim": "9.1.16", + "@storybook/react-dom-shim": "9.1.15", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" @@ -5886,17 +5869,17 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.16" + "storybook": "^9.1.15" } }, "node_modules/@storybook/builder-vite": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.16.tgz", - "integrity": "sha512-CyvYA5w1BKeSVaRavKi+euWxLffshq0v9Rz/5E9MKCitbYtjwkDH6UMIYmcbTs906mEBuYqrbz3nygDP0ppodw==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-9.1.15.tgz", + "integrity": "sha512-GZkx72cBnCuTL/cVOIWIicB4GCmZWx52zFGSC/qHOT/sKcUkrIoQSpVljqyPa66woHyUeSZX4mu7aGj5A27QVg==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf-plugin": "9.1.16", + "@storybook/csf-plugin": "9.1.15", "ts-dedent": "^2.0.0" }, "funding": { @@ -5904,14 +5887,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.16", + "storybook": "^9.1.15", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.16.tgz", - "integrity": "sha512-GKlNNlmWeFBQxhQY5hZOSnFGbeKq69jal0dYNWoSImTjor28eYRHb9iQkDzRpijLPizBaB9MlxLsLrgFDp7adA==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-9.1.15.tgz", + "integrity": "sha512-UThWh7V3+zd+71XdIsNFkrNslkjyaD/HQPnjWGWBCU4ZWNWRSPd3r0r02nH0zzo+NBi0V4vzNDg/PmfD51iaOg==", "dev": true, "license": "MIT", "dependencies": { @@ -5922,7 +5905,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^9.1.16" + "storybook": "^9.1.15" } }, "node_modules/@storybook/global": { @@ -5946,14 +5929,14 @@ } }, "node_modules/@storybook/react": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-9.1.16.tgz", - "integrity": "sha512-M/SkHJJdtiGpodBJq9+DYmSkEOD+VqlPxKI+FvbHESTNs//1IgqFIjEWetd8quhd9oj/gvo4ICBAPu+UmD6M9w==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-9.1.15.tgz", + "integrity": "sha512-tdd1Od3roaEQ2rjqk1L15yR/N2y/SLNcpPNp3n9AQT1eDPdbKzIzue7u1eW9KUFdwSF9S8xG35roDUkKwBJogQ==", "dev": true, "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "9.1.16" + "@storybook/react-dom-shim": "9.1.15" }, "engines": { "node": ">=20.0.0" @@ -5965,7 +5948,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.16", + "storybook": "^9.1.15", "typescript": ">= 4.9.x" }, "peerDependenciesMeta": { @@ -5975,9 +5958,9 @@ } }, "node_modules/@storybook/react-dom-shim": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.16.tgz", - "integrity": "sha512-MsI4qTxdT6lMXQmo3IXhw3EaCC+vsZboyEZBx4pOJ+K/5cDJ6ZoQ3f0d4yGpVhumDxaxlnNAg954+f8WWXE1rQ==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-9.1.15.tgz", + "integrity": "sha512-l6smvNwxh6kp2U/BupzQ4/NSraTWysZcAe2x+GO5CiIIB8Jbi41XLu5XIHI/GQRnNqpXXE3uMImiHGOORmHEXA==", "dev": true, "license": "MIT", "funding": { @@ -5987,20 +5970,20 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.16" + "storybook": "^9.1.15" } }, "node_modules/@storybook/react-vite": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/@storybook/react-vite/-/react-vite-9.1.16.tgz", - "integrity": "sha512-WRKSq0XfQ/Qx66aKisQCfa/1UKwN9HjVbY6xrmsX7kI5zBdITxIcKInq6PWoPv91SJD7+Et956yX+F86R1aEXw==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/@storybook/react-vite/-/react-vite-9.1.15.tgz", + "integrity": "sha512-ORD3swzehAx6o7Sw/wmXr/L5Q4FANPsc1+G5s6OTfmbWNDy/e803h7lsUUFwokh7PeYgylJzbPMQ8HnkNghN0A==", "dev": true, "license": "MIT", "dependencies": { "@joshwooding/vite-plugin-react-docgen-typescript": "0.6.1", "@rollup/pluginutils": "^5.0.2", - "@storybook/builder-vite": "9.1.16", - "@storybook/react": "9.1.16", + "@storybook/builder-vite": "9.1.15", + "@storybook/react": "9.1.15", "find-up": "^7.0.0", "magic-string": "^0.30.0", "react-docgen": "^8.0.0", @@ -6017,7 +6000,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^9.1.16", + "storybook": "^9.1.15", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, @@ -6156,13 +6139,12 @@ } }, "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "license": "MIT", "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" + "@types/deep-eql": "*" } }, "node_modules/@types/conventional-commits-parser": { @@ -6243,9 +6225,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz", + "integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==", "dev": true, "license": "MIT", "dependencies": { @@ -6266,14 +6248,14 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "version": "18.3.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz", + "integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==", "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", - "csstype": "^3.2.2" + "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { @@ -6321,6 +6303,16 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@vitejs/plugin-react/node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@vitest/browser": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-3.2.4.tgz", @@ -6565,20 +6557,6 @@ "node": ">=18.12.0" } }, - "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@zkochan/js-yaml": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", @@ -6673,9 +6651,9 @@ } }, "node_modules/ansi-escapes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", - "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz", + "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6789,13 +6767,13 @@ } }, "node_modules/ast-v8-to-istanbul": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz", - "integrity": "sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.5.tgz", + "integrity": "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", + "@jridgewell/trace-mapping": "^0.3.30", "estree-walker": "^3.0.3", "js-tokens": "^9.0.1" } @@ -6916,9 +6894,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.2.tgz", - "integrity": "sha512-PxSsosKQjI38iXkmb3d0Y32efqyA0uW4s41u4IVBsLlWLhCiYNpH/AfNOVWRqCQBlD8TFJTz6OUWNd4DFJCnmw==", + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.13.tgz", + "integrity": "sha512-7s16KR8io8nIBWQyCYhmFhd+ebIzb9VKTzki+wOJXHTxTnV6+mFGH3+Jwn1zoKaY9/H9T/0BcKCZnzXljPnpSQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6986,9 +6964,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", "dev": true, "funding": [ { @@ -7006,11 +6984,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -7125,9 +7103,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "version": "1.0.30001748", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001748.tgz", + "integrity": "sha512-5P5UgAr0+aBmNiplks08JLw+AW/XG/SurlgZLgB1dDLfAw7EfRGxIwzPHxdSCGY/BTKDqIVyJL87cCN6s0ZR0w==", "dev": true, "funding": [ { @@ -7222,9 +7200,9 @@ } }, "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==", "dev": true, "license": "MIT" }, @@ -7292,9 +7270,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", "engines": { @@ -7514,9 +7492,9 @@ } }, "node_modules/commander": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", - "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", "dev": true, "license": "MIT", "engines": { @@ -7661,6 +7639,26 @@ "typescript": ">=5" } }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -7683,9 +7681,9 @@ "license": "MIT" }, "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/dargs": { @@ -7833,10 +7831,9 @@ } }, "node_modules/diff": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz", - "integrity": "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -7943,9 +7940,9 @@ "license": "MIT" }, "node_modules/effect": { - "version": "3.19.8", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.19.8.tgz", - "integrity": "sha512-OmLw8EfH02vdmyU2fO4uY9He/wepwKI5E/JNpE2pseaWWUbaYOK9UlxIiKP20ZEqQr+S/jSqRDGmpiqD/2DeCQ==", + "version": "3.18.4", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", + "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", "dev": true, "license": "MIT", "dependencies": { @@ -7954,9 +7951,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.265", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.265.tgz", - "integrity": "sha512-B7IkLR1/AE+9jR2LtVF/1/6PFhY5TlnEHnlrKmGk7PvkJibg5jr+mLXLLzq3QYl6PA1T/vLDthQPqIPAlS/PPA==", + "version": "1.5.232", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.232.tgz", + "integrity": "sha512-ENirSe7wf8WzyPCibqKUG1Cg43cPaxH4wRR7AJsX7MCABCHBIOFqvaYODSLKUuZdraxUTHRE/0A2Aq8BYKEHOg==", "dev": true, "license": "ISC" }, @@ -8143,13 +8140,15 @@ } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/esprima": { @@ -8338,6 +8337,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8492,20 +8501,6 @@ "js-yaml": "^3.13.1" } }, - "node_modules/front-matter/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -8656,9 +8651,9 @@ } }, "node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -8848,9 +8843,9 @@ "license": "MIT" }, "node_modules/human-id": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.3.tgz", - "integrity": "sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.2.tgz", + "integrity": "sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==", "dev": true, "license": "MIT", "bin": { @@ -8994,14 +8989,14 @@ } }, "node_modules/intl-messageformat": { - "version": "10.7.18", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", - "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==", + "version": "10.7.17", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.17.tgz", + "integrity": "sha512-0Ugaf65B2J76rb31drgNF1l6bGEDkbIiYc2Glx6jaZINHnwa5kDRGy8KXYuA+/8P4G0c9prAFhfVhQJJfzUuvQ==", "license": "BSD-3-Clause", "dependencies": { - "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/ecma402-abstract": "2.3.5", "@formatjs/fast-memoize": "2.2.7", - "@formatjs/icu-messageformat-parser": "2.11.4", + "@formatjs/icu-messageformat-parser": "2.11.3", "tslib": "^2.8.0" } }, @@ -9105,13 +9100,16 @@ } }, "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-node": { @@ -9184,13 +9182,13 @@ } }, "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9426,25 +9424,19 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js-yaml/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -9484,9 +9476,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true, "license": "MIT" }, @@ -9579,6 +9571,26 @@ "typescript": ">=5.0.4 <7" } }, + "node_modules/knip/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/knip/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/knip/node_modules/strip-json-comments": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", @@ -9614,23 +9626,19 @@ } }, "node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" }, "node_modules/lint-staged": { - "version": "16.2.7", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.7.tgz", - "integrity": "sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow==", + "version": "16.2.6", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.6.tgz", + "integrity": "sha512-s1gphtDbV4bmW1eylXpVMk2u7is7YsrLl8hzrtvC70h4ByhcMLZFY01Fx05ZUDNuv1H8HO4E+e2zgejV1jVwNw==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^14.0.2", + "commander": "^14.0.1", "listr2": "^9.0.5", "micromatch": "^4.0.8", "nano-spawn": "^2.0.0", @@ -9825,6 +9833,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.startcase": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", @@ -9847,92 +9862,59 @@ "license": "MIT" }, "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -10063,9 +10045,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -11183,9 +11165,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", + "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", "dev": true, "license": "MIT" }, @@ -11337,6 +11319,19 @@ "node": ">=8" } }, + "node_modules/nx/node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nx/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -11377,6 +11372,63 @@ "node": ">=8" } }, + "node_modules/nx/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nx/node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/nx/node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/nx/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nx/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -11409,6 +11461,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nx/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nx/node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -11524,122 +11599,81 @@ } }, "node_modules/ora": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", - "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, "license": "MIT", "dependencies": { - "bl": "^4.0.3", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/ora/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/ora/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/ora/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" + "node": ">=12" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/outdent": { @@ -11650,35 +11684,35 @@ "license": "MIT" }, "node_modules/oxc-resolver": { - "version": "11.15.0", - "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.15.0.tgz", - "integrity": "sha512-Hk2J8QMYwmIO9XTCUiOH00+Xk2/+aBxRUnhrSlANDyCnLYc32R1WSIq1sU2yEdlqd53FfMpPEpnBYIKQMzliJw==", + "version": "11.16.0", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.16.0.tgz", + "integrity": "sha512-I4sHGa1fZUpTQ9ftS0E0cBYbBjNnIKXRSX/trFMIJDIJ4n21dCrLAZhnJS0TSfRIRqZNFyceNZr2kablfgNyTA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxc-resolver/binding-android-arm-eabi": "11.15.0", - "@oxc-resolver/binding-android-arm64": "11.15.0", - "@oxc-resolver/binding-darwin-arm64": "11.15.0", - "@oxc-resolver/binding-darwin-x64": "11.15.0", - "@oxc-resolver/binding-freebsd-x64": "11.15.0", - "@oxc-resolver/binding-linux-arm-gnueabihf": "11.15.0", - "@oxc-resolver/binding-linux-arm-musleabihf": "11.15.0", - "@oxc-resolver/binding-linux-arm64-gnu": "11.15.0", - "@oxc-resolver/binding-linux-arm64-musl": "11.15.0", - "@oxc-resolver/binding-linux-ppc64-gnu": "11.15.0", - "@oxc-resolver/binding-linux-riscv64-gnu": "11.15.0", - "@oxc-resolver/binding-linux-riscv64-musl": "11.15.0", - "@oxc-resolver/binding-linux-s390x-gnu": "11.15.0", - "@oxc-resolver/binding-linux-x64-gnu": "11.15.0", - "@oxc-resolver/binding-linux-x64-musl": "11.15.0", - "@oxc-resolver/binding-openharmony-arm64": "11.15.0", - "@oxc-resolver/binding-wasm32-wasi": "11.15.0", - "@oxc-resolver/binding-win32-arm64-msvc": "11.15.0", - "@oxc-resolver/binding-win32-ia32-msvc": "11.15.0", - "@oxc-resolver/binding-win32-x64-msvc": "11.15.0" + "@oxc-resolver/binding-android-arm-eabi": "11.16.0", + "@oxc-resolver/binding-android-arm64": "11.16.0", + "@oxc-resolver/binding-darwin-arm64": "11.16.0", + "@oxc-resolver/binding-darwin-x64": "11.16.0", + "@oxc-resolver/binding-freebsd-x64": "11.16.0", + "@oxc-resolver/binding-linux-arm-gnueabihf": "11.16.0", + "@oxc-resolver/binding-linux-arm-musleabihf": "11.16.0", + "@oxc-resolver/binding-linux-arm64-gnu": "11.16.0", + "@oxc-resolver/binding-linux-arm64-musl": "11.16.0", + "@oxc-resolver/binding-linux-ppc64-gnu": "11.16.0", + "@oxc-resolver/binding-linux-riscv64-gnu": "11.16.0", + "@oxc-resolver/binding-linux-riscv64-musl": "11.16.0", + "@oxc-resolver/binding-linux-s390x-gnu": "11.16.0", + "@oxc-resolver/binding-linux-x64-gnu": "11.16.0", + "@oxc-resolver/binding-linux-x64-musl": "11.16.0", + "@oxc-resolver/binding-openharmony-arm64": "11.16.0", + "@oxc-resolver/binding-wasm32-wasi": "11.16.0", + "@oxc-resolver/binding-win32-arm64-msvc": "11.16.0", + "@oxc-resolver/binding-win32-ia32-msvc": "11.16.0", + "@oxc-resolver/binding-win32-x64-msvc": "11.16.0" } }, "node_modules/p-filter": { @@ -11809,12 +11843,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-json/node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -11955,13 +11983,13 @@ } }, "node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.57.0" + "playwright-core": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -11974,9 +12002,9 @@ } }, "node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -12346,19 +12374,10 @@ "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-diff-viewer-continued/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/react-docgen": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-8.0.2.tgz", - "integrity": "sha512-+NRMYs2DyTP4/tqWz371Oo50JqmWltR1h2gcdgUMAWZJIAvrd0/SqlCfx7tpzpl/s36rzw6qH2MjoNrxtRNYhA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-8.0.1.tgz", + "integrity": "sha512-kQKsqPLplY3Hx4jGnM3jpQcG3FQDt7ySz32uTHt3C9HAe45kNXG+3o16Eqn3Fw1GtMfHoN3b4J/z2e6cZJCmqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12418,9 +12437,9 @@ "license": "MIT" }, "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "license": "MIT", "engines": { @@ -12480,30 +12499,16 @@ "node": ">=6" } }, - "node_modules/read-yaml-file/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" @@ -12637,12 +12642,12 @@ } }, "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.1", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -12712,14 +12717,14 @@ "license": "MIT" }, "node_modules/rimraf": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", - "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "glob": "^13.0.0", - "package-json-from-dist": "^1.0.1" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" @@ -12732,16 +12737,22 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", - "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "minimatch": "^10.1.1", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { "node": "20 || >=22" }, @@ -12749,24 +12760,14 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", - "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "node_modules/rimraf/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { "node": "20 || >=22" @@ -12775,10 +12776,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -12793,9 +12804,9 @@ } }, "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "version": "4.52.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", + "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", "devOptional": true, "license": "MIT", "dependencies": { @@ -12809,28 +12820,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", + "@rollup/rollup-android-arm-eabi": "4.52.4", + "@rollup/rollup-android-arm64": "4.52.4", + "@rollup/rollup-darwin-arm64": "4.52.4", + "@rollup/rollup-darwin-x64": "4.52.4", + "@rollup/rollup-freebsd-arm64": "4.52.4", + "@rollup/rollup-freebsd-x64": "4.52.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", + "@rollup/rollup-linux-arm-musleabihf": "4.52.4", + "@rollup/rollup-linux-arm64-gnu": "4.52.4", + "@rollup/rollup-linux-arm64-musl": "4.52.4", + "@rollup/rollup-linux-loong64-gnu": "4.52.4", + "@rollup/rollup-linux-ppc64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-gnu": "4.52.4", + "@rollup/rollup-linux-riscv64-musl": "4.52.4", + "@rollup/rollup-linux-s390x-gnu": "4.52.4", + "@rollup/rollup-linux-x64-gnu": "4.52.4", + "@rollup/rollup-linux-x64-musl": "4.52.4", + "@rollup/rollup-openharmony-arm64": "4.52.4", + "@rollup/rollup-win32-arm64-msvc": "4.52.4", + "@rollup/rollup-win32-ia32-msvc": "4.52.4", + "@rollup/rollup-win32-x64-gnu": "4.52.4", + "@rollup/rollup-win32-x64-msvc": "4.52.4", "fsevents": "~2.3.2" } }, @@ -13080,9 +13091,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", "dev": true, "license": "MIT" }, @@ -13100,9 +13111,9 @@ } }, "node_modules/storybook": { - "version": "9.1.16", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.16.tgz", - "integrity": "sha512-339U14K6l46EFyRvaPS2ZlL7v7Pb+LlcXT8KAETrGPxq8v1sAjj2HAOB6zrlAK3M+0+ricssfAwsLCwt7Eg8TQ==", + "version": "9.1.15", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-9.1.15.tgz", + "integrity": "sha512-es7uDdEwRVVUAt7XLAZZ1hicOq9r4ov5NFeFPpa2YEyAsyHYOCr0CTlHBfslWG6D5EVNWK3kVIIuW8GHB6hEig==", "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", @@ -13755,9 +13766,9 @@ } }, "node_modules/strip-indent": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", - "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.0.tgz", + "integrity": "sha512-OA95x+JPmL7kc7zCu+e+TeYxEiaIyndRx0OrBcK2QPPH09oAndr2ALvymxWA+Lx1PYYvFUm4O63pRkdJAaW96w==", "dev": true, "license": "MIT", "engines": { @@ -13807,18 +13818,18 @@ "license": "MIT" }, "node_modules/sucrase": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", - "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", + "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", - "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { @@ -13839,13 +13850,6 @@ "node": ">= 6" } }, - "node_modules/sucrase/node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -13915,31 +13919,12 @@ "node": ">=18.18.0" } }, - "node_modules/syncpack/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/syncpack/node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/syncpack/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "Python-2.0" }, "node_modules/syncpack/node_modules/commander": { "version": "13.1.0", @@ -13951,13 +13936,6 @@ "node": ">=18" } }, - "node_modules/syncpack/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, "node_modules/syncpack/node_modules/globby": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", @@ -13989,67 +13967,17 @@ "node": ">= 4" } }, - "node_modules/syncpack/node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/syncpack/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/syncpack/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/syncpack/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "node_modules/syncpack/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/syncpack/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/syncpack/node_modules/minimatch": { @@ -14068,30 +13996,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/syncpack/node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/syncpack/node_modules/path-type": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", @@ -14132,40 +14036,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/syncpack/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/syncpack/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/syncpack/node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -14508,9 +14378,9 @@ "license": "0BSD" }, "node_modules/tsup": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz", - "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.0.tgz", + "integrity": "sha512-VmBp77lWNQq6PfuMqCHD3xWl22vEoWsKajkF8t+yMBawlUS8JzEI+vOVMeuNZIuMML8qXRizFKi9oD5glKQVcQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14519,14 +14389,14 @@ "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", - "esbuild": "^0.27.0", + "esbuild": "^0.25.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", - "source-map": "^0.7.6", + "source-map": "0.8.0-beta.0", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", @@ -14560,40 +14430,557 @@ } } }, - "node_modules/tsup/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "node_modules/tsup/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">= 12" + "node": ">=18" } }, - "node_modules/tsup/node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "node_modules/tsup/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "node_modules/tsup/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", + "node_modules/tsup/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsup/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "deprecated": "The work that was done in this beta branch won't be included in future versions", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsup/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tsup/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tsup/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/tsup/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { @@ -14648,9 +15035,9 @@ } }, "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dev": true, "license": "MIT", "dependencies": { @@ -14692,9 +15079,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dev": true, "license": "MIT", "dependencies": { @@ -14731,9 +15118,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -15332,9 +15719,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", "dev": true, "license": "ISC", "bin": { @@ -15342,9 +15729,6 @@ }, "engines": { "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { @@ -15409,9 +15793,9 @@ } }, "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", "dev": true, "license": "MIT", "engines": { @@ -15422,9 +15806,9 @@ } }, "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "dev": true, "license": "MIT", "funding": { @@ -15487,6 +15871,11 @@ "react-dom": "18.x || 19.x" } }, + "packages/compile-readme-tests": { + "name": "@bento/compile-readme-tests", + "version": "0.0.0", + "extraneous": true + }, "packages/container": { "name": "@bento/container", "version": "0.2.1", @@ -15500,6 +15889,22 @@ "react-dom": "18.x || 19.x" } }, + "packages/control": { + "name": "@bento/control", + "version": "0.1.2", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@bento/slots": "^0.1.3", + "@bento/text": "^0.1.2", + "@bento/use-props": "^0.1.1", + "react-aria": "^3.44.0" + }, + "peerDependencies": { + "react": "18.x || 19.x", + "react-dom": "18.x || 19.x" + } + }, "packages/create-external-store": { "name": "@bento/create-external-store", "version": "0.1.1", @@ -15673,7 +16078,8 @@ }, "packages/internal-props": { "name": "@bento/internal-props", - "version": "0.1.1", + "version": "0.1.0", + "extraneous": true, "license": "MIT", "peerDependencies": { "react": "18.x || 19.x", @@ -15806,6 +16212,10 @@ "react-aria": "^3.44.0", "use-deep-compare": "^1.3.0" }, + "devDependencies": { + "@bento/environment": "*", + "@bento/use-props": "*" + }, "peerDependencies": { "react": "18.x || 19.x", "react-dom": "18.x || 19.x" @@ -15893,7 +16303,6 @@ "license": "MIT", "dependencies": { "@bento/box": "^0.2.0", - "@bento/internal-props": "^0.1.1", "@bento/types": "^0.1.0", "@react-aria/utils": "^3.30.0" }, diff --git a/packages/box/src/index.tsx b/packages/box/src/index.tsx index 4b420dd56..f08d83752 100644 --- a/packages/box/src/index.tsx +++ b/packages/box/src/index.tsx @@ -26,6 +26,19 @@ export interface EnvContext { */ sprite: string; + /** + * Indicates if the environment is currently locked. + * When locked, modifications applied after the lock are flagged with data-override. + */ + locked: boolean; + + /** + * Current lock generation number. + * Increments each time a new Environment with lock={true} is created. + * Used to determine if a slot was added before or after a lock boundary. + */ + lockGeneration: number; + [key: string]: any; } @@ -44,6 +57,12 @@ export interface SlotsContext { * Indicator if a `components` override has been applied to the parent or current component. */ override: boolean; + + /** + * Tracks the lock generation for each slot. + * Maps slot name to the lockGeneration value when the slot was first assigned. + */ + slotGenerations: Record; } export interface BoxContext { @@ -96,13 +115,16 @@ export function defaults(root?: RootNode): BoxContext { env: { components: {}, sprite: '', + locked: false, + lockGeneration: 0, document: () => getDocument(root), window: () => getWindow(root) }, slots: { override: false, namespace: [], - assigned: {} + assigned: {}, + slotGenerations: {} } }; } diff --git a/packages/box/test/context.node.test.tsx b/packages/box/test/context.node.test.tsx index 2ce21a9bf..98b907d38 100644 --- a/packages/box/test/context.node.test.tsx +++ b/packages/box/test/context.node.test.tsx @@ -104,7 +104,7 @@ describe('@bento/box', function bento() { }; const result = renderToString( - + {function render(ctx) { @@ -175,8 +175,8 @@ describe('@bento/box', function bento() { const result = renderToString( document, window: () => window }, - slots: { override: true, namespace: ['parent', 'child'], assigned: {} } + env: { components: {}, sprite: '', document: () => document, window: () => window, locked: false, lockGeneration: 0 }, + slots: { override: true, namespace: ['parent', 'child'], assigned: {}, slotGenerations: {} } }} > diff --git a/packages/button/test/button.node.test.tsx b/packages/button/test/button.node.test.tsx index 0f0797bb9..8aa104955 100644 --- a/packages/button/test/button.node.test.tsx +++ b/packages/button/test/button.node.test.tsx @@ -31,22 +31,6 @@ describe('@bento/button', function bento() { }); describe('#slots', function slots() { - it('renders correct [data-override] attribute values', function overrides() { - const result = renderToStringButton({ - className: 'custom-class', - style: { color: 'red' }, - children:
Press me
, - onClick: () => void 0, - onPress: () => void 0, - onPressStart: () => void 0, - onPressEnd: () => void 0, - onPressUp: () => void 0, - onPressChange: () => void 0 - }); - - assume(result).includes('data-override="className style"'); - }); - it('introduced the `pressable` slot to the Pressable component', function pressable() { const result = renderToStringButton({ children:
Press me
, @@ -57,7 +41,6 @@ describe('@bento/button', function bento() { } }); - assume(result).includes('data-override="slot"'); assume(result).includes('data-foo="bar"'); }); }); diff --git a/packages/container/test/container.browser.test.tsx b/packages/container/test/container.browser.test.tsx index db2dd360b..20a9b644d 100644 --- a/packages/container/test/container.browser.test.tsx +++ b/packages/container/test/container.browser.test.tsx @@ -110,17 +110,6 @@ describe('@bento/container', function bento() { expect(element?.children[1].textContent).toBe('Second'); }); - it('tracks overrides via data-override attribute', function tracksOverrides() { - const { container } = render( - - Overridden - - ); - const element = container.firstChild as HTMLElement; - - expect(element?.getAttribute('data-override')).toBeTruthy(); - }); - it('renders with data attributes', function rendersDataAttributes() { const { container } = render( diff --git a/packages/divider/test/divider.node.test.tsx b/packages/divider/test/divider.node.test.tsx index efa83d54b..bce540806 100644 --- a/packages/divider/test/divider.node.test.tsx +++ b/packages/divider/test/divider.node.test.tsx @@ -46,15 +46,6 @@ describe('@bento/divider', function bento() { assume(result).doesnt.include(' orientation='); }); - it('renders correct [data-override] attribute values when directly overridden', function overrides() { - const result = renderToStringDivider({ - className: 'custom-class', - style: { color: 'red' } - }); - - assume(result).includes('data-override="className style"'); - }); - it('allows user to override classname fully', function classname() { const result = renderToStringDivider({ className: 'custom-class' diff --git a/packages/divider/test/examples.browser.test.tsx b/packages/divider/test/examples.browser.test.tsx index ad6a18fac..2568d183e 100644 --- a/packages/divider/test/examples.browser.test.tsx +++ b/packages/divider/test/examples.browser.test.tsx @@ -36,7 +36,6 @@ describe('@bento/divider examples', function bento() { expect(divider).toHaveAttribute('style'); expect(divider).toHaveStyle('height: 100px'); - expect(divider).toHaveAttribute('data-override', 'style'); }); it('renders a vertical divider in a div', function verticalInDivTest() { diff --git a/packages/environment/CONCEPTS.mdx b/packages/environment/CONCEPTS.mdx index 76ab4eb85..e3f55614c 100644 --- a/packages/environment/CONCEPTS.mdx +++ b/packages/environment/CONCEPTS.mdx @@ -3,14 +3,16 @@ import * as Stories from './environment.stories.tsx'; import ComponentLevelExample from './examples/component-level.tsx?raw'; import CustomButtonExample from './examples/custom-button.tsx?raw'; +import LockNoOverrideExample from './examples/lock-no-override.tsx?raw'; +import LockWithOverrideExample from './examples/lock-with-override.tsx?raw'; # Application level configuration -The `Environment` component is the main entry point for configuring Bento -components in your application. It allows you to set up global configurations, -such as components, and other settings that will be applied throughout your +The `Environment` component is the main entry point for configuring Bento +components in your application. It allows you to set up global configurations, +such as components, and other settings that will be applied throughout your application. This allows you to easily customize the behavior of specific set of components. @@ -25,7 +27,7 @@ Bento. This is useful when you want to customize the behavior or appearance of a specific component. You can pass a mapping of component names to their corresponding components. The keys in the object should match the component names used by Bento, and the values should be the new components you want to -use. +use. This is useful when you want to use a custom implementation of a component or when you want to use a different library altogether. For example, if you want @@ -34,7 +36,7 @@ it like this: -This will replace the default Bento button with your custom button component +This will replace the default Bento button with your custom button component throughout your application. ### Overrides @@ -65,3 +67,37 @@ application code. This is useful when you want to test a new component or a new version of a component without modifying the application code. The custom button example shows how to use a different component implementation for A/B testing: + +## Lock Boundaries + +When you're building a design system on top of Bento, you'll often compose components together internally using slots, className, and style props. Without lock boundaries, all these internal modifications get flagged with `data-override` attributes, which makes it really hard to tell the difference between your design system's internal structure and actual customizations made by people using your design system. + +Lock boundaries solve this by creating a clear line between "this is how we built it" and "this is what someone changed." Think of it as drawing a circle around your component and saying "everything inside this circle is intentional design system composition." + +### How it works + +The mechanism uses a generation counter. When you wrap a component with ``, Bento increments a generation number. Every slot modification gets tagged with the current generation number. Later, when the component renders, Bento checks: was this slot created before or after the lock? If it was created before (lower generation number), it came from a consumer, so it gets flagged. If it was created after (same or higher generation), it's part of your design system's internal structure, so no flag. + +Here's a practical example. Let's say you're building a design system and you create a component that internally uses a Button and RadioGroup: + + + +Notice the `` wrapper. Everything you do with slots inside that wrapper is considered internal composition. The `root.trigger` slot that changes the button text, the `group.label` and `group.description` slots that style the radio group—none of these get `data-override` attributes because they're all happening after the lock. + +Now when someone uses your design system component and wants to customize it: + + + +This slot modification happens *before* entering your locked environment (because it's passed as a prop to `DesignSystemVersion`). Bento sees it crossed the lock boundary and adds `data-override="slot"`. Now you know exactly what your consumers are customizing. + +### When to use this + +Use lock boundaries when you're building a design system that other developers will consume. If you're just building application components or working directly with Bento primitives, you probably don't need this. The lock is specifically for the boundary between design system authors and design system consumers. + +You might skip locks if you're debugging and want to see all modifications flagged, or if you're building one-off components that won't be reused across teams. + +### What you can do with this information + +Once you have accurate `data-override` tracking, you can build tooling around it. You could create a development mode that warns when consumers override certain slots, track which components are being customized most often to inform your roadmap, or generate migration guides when you need to make breaking changes by analyzing which overrides exist in production. + +The `data-override` attributes are just data attributes in the DOM. Your dev tools, browser extensions, or analytics can read them to understand how your design system is being used in the wild. diff --git a/packages/environment/README.mdx b/packages/environment/README.mdx index 2ba535105..205dc1e88 100644 --- a/packages/environment/README.mdx +++ b/packages/environment/README.mdx @@ -5,6 +5,7 @@ import OverridePropsExample from './examples/override-props.tsx?raw'; import CustomButtonExample from './examples/custom-button.tsx?raw'; import ComponentLevelExample from './examples/component-level.tsx?raw'; import IframeRenderingExample from './examples/iframe-rendering.tsx?raw'; +import LockNoOverrideExample from './examples/lock-no-override.tsx?raw'; @@ -55,7 +56,7 @@ context. In the example below we are using the `react-frame-component` package to render our components in an iframe. By passing the new `document` object as `root` -prop, we can ensure that the components that reference the `document` and +prop, we can ensure that the components that reference the `document` and `window` objects will correctly access the new document and window objects. @@ -94,3 +95,33 @@ can do it like this: + +## Lock Boundaries + +If you're building a design system on top of Bento and distributing components to other teams, the `lock` prop helps you distinguish between your internal component composition and modifications made by your consumers. + +The problem this solves is simple: when you compose components internally using slots, all those modifications show up with `data-override` attributes. This makes it impossible to tell which modifications are part of your design system's intentional structure versus which ones are customizations made by the people using your components. + +Here's what it looks like in practice: + + + +The `` wrapper tells Bento that everything inside is internal to your design system. When you modify slots within that boundary (like changing the button text or adding className to the radio labels), those modifications won't get flagged with `data-override`. + +But when someone using your design system passes their own slots: + +```tsx + +``` + +That modification happens outside your lock boundary, so it gets flagged with `data-override="slot"`. Now you can tell the difference. + +This information becomes useful when you want to understand how your design system is actually being used. You could build dev tools that warn about certain overrides, track usage patterns to inform your roadmap, or generate migration guides based on which slots people are actually customizing in production. + +For more details about how the generation tracking system works and when to use locks, see the [Concepts](/docs/environment-concepts--docs) page. + +## Props + + diff --git a/packages/environment/examples/lock-no-override.tsx b/packages/environment/examples/lock-no-override.tsx new file mode 100644 index 000000000..d4990524b --- /dev/null +++ b/packages/environment/examples/lock-no-override.tsx @@ -0,0 +1,86 @@ +import { Environment } from '@bento/environment'; +import { withSlots } from '@bento/slots'; +import { useProps } from '@bento/use-props'; +import { Button } from '@bento/button'; +import { Container } from '@bento/container'; +import { RadioGroup, Radio } from '@bento/radio'; +/* v8 ignore next */ +import React from 'react'; + +// Cast components to accept children (workaround for strict slot types) +const TypedContainer = Container as React.FC; +const TypedButton = Button as React.FC; +const TypedRadioGroup = RadioGroup as React.FC; +const TypedRadio = Radio as React.FC; + +/** + * Interface for component props. + * + * @interface ComponentProps + * @public + */ +interface ComponentProps { + [key: string]: any; +} + +/** + * Composite component with internal slots. + * + * @param {ComponentProps} props - The component props. + * @returns {JSX.Element} The rendered composed component. + * @public + */ +const Composed = withSlots('LockNoOverride.Composed', function ComposedComponent(props: ComponentProps) { + const slots = { + 'group.label': { className: 'label' }, + 'group.description': { className: 'describe' } + }; + + return ( + + Press Me + + Apple + Banana + Orange + + + ); +}); + +/** + * Design system component with lock boundary. + * + * @param {ComponentProps} props - The component props. + * @returns {JSX.Element} The rendered design system component. + * @public + */ +export const DesignSystemVersion = withSlots( + 'LockNoOverride.DSVersion', + function DSVersionComponent(props: ComponentProps) { + const { props: p } = useProps(props); + const slots = { + 'root.trigger': { + children: 'Click Me' + } + }; + + return ( + + + + ); + } +); + +/** + * Example demonstrating lock with NO consumer overrides. + * Expected: NO data-override attributes anywhere. + * All slots (trigger, label, description) are internal composition. + * + * @returns {JSX.Element} The rendered example. + * @public + */ +export const LockNoOverride: React.FC = function LockNoOverride() { + return ; +}; diff --git a/packages/environment/examples/lock-with-override.tsx b/packages/environment/examples/lock-with-override.tsx new file mode 100644 index 000000000..17b80eea9 --- /dev/null +++ b/packages/environment/examples/lock-with-override.tsx @@ -0,0 +1,16 @@ +/* v8 ignore next */ +import React from 'react'; +// Reuse the components from the lock-no-override example +import { DesignSystemVersion } from './lock-no-override'; + +/** + * Example demonstrating lock WITH consumer override. + * Expected: data-override ONLY on the button (trigger slot). + * Consumer modifies the trigger slot, internal label/description are not flagged. + * + * @returns {JSX.Element} The rendered example. + * @public + */ +export const LockWithOverride: React.FC = function LockWithOverride() { + return ; +}; diff --git a/packages/environment/src/index.tsx b/packages/environment/src/index.tsx index b1faa6266..c2f638640 100644 --- a/packages/environment/src/index.tsx +++ b/packages/environment/src/index.tsx @@ -35,6 +35,16 @@ export interface EnvironmentProps { */ sprite?: string; + /** + * When true, creates a lock boundary. Slot modifications applied after this + * lock will be detected and flagged with data-override attributes. + * This is used by design systems to distinguish between internal composition + * and consumer modifications. + * + * @defaultValue false + */ + lock?: boolean; + // // Catch all, to allow users specify custom configuration that can be shared // between Bento component that does need strong typing. @@ -55,6 +65,7 @@ export interface EnvironmentProps { * - If a value in the configuration is an array, it will be concatenated with the existing array in the context. * - If a value in the configuration is an object, it will be deeply merged with the existing object in the context. * - Primitive values in the configuration will overwrite the existing values in the context. + * - When `lock={true}`, the lockGeneration is incremented, creating a boundary for detecting consumer modifications. * * @example * ```tsx @@ -62,8 +73,16 @@ export interface EnvironmentProps { * * * ``` + * + * @example + * ```tsx + * // Create a lock boundary for a design system component + * + * + * + * ``` */ -export function Environment({ children, ...config }: EnvironmentProps) { +export function Environment({ children, lock = false, ...config }: EnvironmentProps) { let ctx = { ...useContext>>(Box) }; const context = useDeepCompareMemo( @@ -71,6 +90,40 @@ export function Environment({ children, ...config }: EnvironmentProps) { const { root, ...options } = config; ctx.env = merge(ctx.env, options) as EnvContext>; + ctx.slots = { ...ctx.slots }; + + // Handle lock generation + if (lock && !ctx.env.locked) { + // First lock in the tree + // IMPORTANT: Before incrementing generation, tag ALL existing slots + // with the current (pre-lock) generation. This marks them as "consumer slots" + // that were passed before the lock boundary. + const preLockGeneration = ctx.env.lockGeneration; + ctx.slots.slotGenerations = { ...ctx.slots.slotGenerations }; + + for (const slotKey in ctx.slots.assigned) { + if (!(slotKey in ctx.slots.slotGenerations)) { + ctx.slots.slotGenerations[slotKey] = preLockGeneration; + } + } + + // Now set locked and increment generation + ctx.env.locked = true; + ctx.env.lockGeneration = ctx.env.lockGeneration + 1; + } else if (lock && ctx.env.locked) { + // Nested lock - tag existing slots and increment generation + const preLockGeneration = ctx.env.lockGeneration; + ctx.slots.slotGenerations = { ...ctx.slots.slotGenerations }; + + for (const slotKey in ctx.slots.assigned) { + if (!(slotKey in ctx.slots.slotGenerations)) { + ctx.slots.slotGenerations[slotKey] = preLockGeneration; + } + } + + ctx.env.lockGeneration = ctx.env.lockGeneration + 1; + } + // If lock={false}, don't increment generation (inherit parent's generation) if (root) { const { document, window } = defaults(root).env; @@ -79,7 +132,7 @@ export function Environment({ children, ...config }: EnvironmentProps) { return ctx; }, - [ctx, config] + [ctx, config, lock] ); return {children}; diff --git a/packages/environment/test/__snapshots__/examples.browser.test.tsx.snap b/packages/environment/test/__snapshots__/examples.browser.test.tsx.snap new file mode 100644 index 000000000..1ba16f324 --- /dev/null +++ b/packages/environment/test/__snapshots__/examples.browser.test.tsx.snap @@ -0,0 +1,7 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`@bento/environment examples > CustomButtonExample > should render the custom button component 1`] = `"

This text will be rendered with default styling

"`; + +exports[`@bento/environment examples > Override > should render the Container component 1`] = `""`; + +exports[`@bento/environment examples > OverrideProps > should render the Container component 1`] = `"
"`; diff --git a/packages/environment/test/environment.browser.test.tsx b/packages/environment/test/environment.browser.test.tsx index 914984877..72d1d1164 100644 --- a/packages/environment/test/environment.browser.test.tsx +++ b/packages/environment/test/environment.browser.test.tsx @@ -66,5 +66,91 @@ describe('@bento/environment', function bento() { assume(env).equals('Hello World'); }); + + it('should handle nested environments with lock boundaries', async function test() { + let firstGeneration: number; + let secondGeneration: number; + + const env = renderToString( + + + {function firstConsumer({ env }) { + firstGeneration = env.lockGeneration; + assume(env.locked).to.equal(true); + + return ( + + + {function secondConsumer({ env }) { + secondGeneration = env.lockGeneration; + assume(env.locked).to.equal(true); + return 'Nested Lock'; + }} + + + ); + }} + + + ); + + assume(env).equals('Nested Lock'); + assume(secondGeneration!).to.be.above(firstGeneration!); + }); + + it('should tag pre-existing slots with generation when entering first lock', async function test() { + const env = renderToString( + document, window: () => window, locked: false, lockGeneration: 0 }, + slots: { override: false, namespace: [], assigned: { mySlot: { className: 'test' } }, slotGenerations: {} } + }} + > + + + {function consumer({ env, slots }) { + // The pre-existing slot should be tagged with generation 0 (before lock) + assume(slots.slotGenerations.mySlot).to.equal(0); + assume(env.lockGeneration).to.equal(1); + assume(env.locked).to.equal(true); + return 'Tagged Slots'; + }} + + + + ); + + assume(env).equals('Tagged Slots'); + }); + + it('should tag pre-existing slots with generation when entering nested lock', async function test() { + const env = renderToString( + + + {function firstConsumer({ env, slots }) { + // Add a slot after first lock + slots.assigned = { ...slots.assigned, nestedSlot: { id: 'nested' } }; + + return ( + + + + {function secondConsumer({ env, slots }) { + // The slot added after first lock should be tagged with generation 1 + assume(slots.slotGenerations.nestedSlot).to.equal(1); + assume(env.lockGeneration).to.equal(2); + return 'Nested Tagged Slots'; + }} + + + + ); + }} + + + ); + + assume(env).equals('Nested Tagged Slots'); + }); }); }); diff --git a/packages/environment/test/examples.browser.test.tsx b/packages/environment/test/examples.browser.test.tsx index 1306e0da9..7c32ace5a 100644 --- a/packages/environment/test/examples.browser.test.tsx +++ b/packages/environment/test/examples.browser.test.tsx @@ -3,8 +3,10 @@ import { ComponentLevelExample } from '../examples/component-level.tsx'; import { CustomButtonExample } from '../examples/custom-button.tsx'; import { OverrideProps } from '../examples/override-props.tsx'; import { Override } from '../examples/override.tsx'; +import { LockNoOverride } from '../examples/lock-no-override.tsx'; +import { LockWithOverride } from '../examples/lock-with-override.tsx'; import { render } from 'vitest-browser-react'; -import { describe, it } from 'vitest'; +import { describe, it, expect } from 'vitest'; import assume from 'assume'; import React from 'react'; @@ -12,34 +14,21 @@ describe('@bento/environment examples', function bento() { describe('Override', function container() { it('should render the Container component', function test() { const { container } = render(); - - const result = container.innerHTML; - - assume(result).equals( - '' - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('OverrideProps', function container() { it('should render the Container component', function test() { const { container } = render(); - - const result = container.innerHTML; - - assume(result).equals( - '
' - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('CustomButtonExample', function container() { it('should render the custom button component', async function testCustomButtonRender() { const { container } = await render(); - const result = container.innerHTML; - assume(result).to.equal( - '

This text will be rendered with default styling

' - ); + expect(container.innerHTML).toMatchSnapshot(); }); it('should not render the BentoButton', async function testBentoButtonNotRendered() { @@ -178,4 +167,106 @@ describe('@bento/environment examples', function bento() { assume(secondUpdatedBgColor).equals('lightgreen'); }); }); + + describe('LockNoOverride', function lockNoOverride() { + it('should render without any data-override attributes', function test() { + const { container } = render(); + const result = container.innerHTML; + + // Should have NO data-override attributes since all slots are internal composition + assume(result).does.not.include('data-override'); + }); + + it('should render the button with internal composition text', function test() { + const { container } = render(); + const button = container.querySelector('button'); + + assume(button).to.not.equal(null); + assume(button?.textContent).equals('Click Me'); + }); + + it('should render the radio group with all options', function test() { + const { container } = render(); + const radioInputs = container.querySelectorAll('input[type="radio"]'); + + assume(radioInputs.length).equals(3); + }); + + it('should have data-slot attributes on slotted components', function test() { + const { container } = render(); + + // Container should have data-slot="root" + const rootSlot = container.querySelector('[data-slot="root"]'); + assume(rootSlot).to.not.equal(null); + + // Button should have data-slot="pressable" + const buttonSlot = container.querySelector('[data-slot="pressable"]'); + assume(buttonSlot).to.not.equal(null); + }); + + it('should have label and description on radio group', function test() { + const { container } = render(); + + // Check for radio group with label attribute + const radioGroup = container.querySelector('[role="radiogroup"]'); + assume(radioGroup).to.not.equal(null); + assume(radioGroup?.getAttribute('label')).equals('Favorite fruit'); + assume(radioGroup?.getAttribute('description')).equals('Pick your favorite'); + }); + }); + + describe('LockWithOverride', function lockWithOverride() { + it('should render with data-override only on the trigger button', function test() { + const { container } = render(); + const button = container.querySelector('button'); + + // Button should have data-override="slot" because consumer modified it + assume(button).to.not.equal(null); + assume(button?.getAttribute('data-override')).equals('slot'); + }); + + it('should render the button with consumer override text', function test() { + const { container } = render(); + const button = container.querySelector('button'); + + assume(button).to.not.equal(null); + assume(button?.textContent).equals('Hello World'); + }); + + it('should have data-slot on slotted components', function test() { + const { container } = render(); + + // Button should have data-slot="pressable" + const buttonSlot = container.querySelector('[data-slot="pressable"]'); + assume(buttonSlot).to.not.equal(null); + + // RadioGroup icons should have data-slot="content" + const iconSlots = container.querySelectorAll('[data-slot="content"]'); + assume(iconSlots.length).equals(3); + }); + + it('should not flag internal composition with data-override', function test() { + const { container } = render(); + + // RadioGroup should not have data-override + const radioGroup = container.querySelector('[role="radiogroup"]'); + assume(radioGroup).to.not.equal(null); + assume(radioGroup?.hasAttribute('data-override')).equals(false); + + // Icons should not have data-override + const icons = container.querySelectorAll('svg'); + icons.forEach(function checkIcon(icon) { + assume(icon.hasAttribute('data-override')).equals(false); + }); + }); + + it('should only have data-override on consumer-modified slots', function test() { + const { container } = render(); + const elementsWithOverride = container.querySelectorAll('[data-override]'); + + // Only the trigger button should have data-override + assume(elementsWithOverride.length).equals(1); + assume(elementsWithOverride[0]?.tagName.toLowerCase()).equals('button'); + }); + }); }); diff --git a/packages/heading/test/heading.node.test.tsx b/packages/heading/test/heading.node.test.tsx index 163d7ae09..990197f2c 100644 --- a/packages/heading/test/heading.node.test.tsx +++ b/packages/heading/test/heading.node.test.tsx @@ -62,20 +62,6 @@ describe('@bento/heading', function bento() { assume(result).match(/^]*>Handgloves<\/span>$/); }); - describe('#slots', function slots() { - it('renders correct [data-override] attribute values', function dataOverride() { - const result = renderToStringHeading({ - children: 'Handgloves', - className: 'custom-class', - style: { - color: 'red' - } - }); - - assume(result).includes('data-override="className style"'); - }); - }); - describe('Public API', function packageSuite() { it('has HeadingProvider attached', function hasProvider() { assume(HeadingProvider).to.be.an('object'); diff --git a/packages/internal-props/CHANGELOG.md b/packages/internal-props/CHANGELOG.md deleted file mode 100644 index d2056d5e0..000000000 --- a/packages/internal-props/CHANGELOG.md +++ /dev/null @@ -1,13 +0,0 @@ -# @bento/internal-props - -## 0.1.1 - -### Patch Changes - -- Adds documentation to all packages; no API or functionality changes. ([#23](https://github.com/godaddy/bento/pull/23) by @kawikabader) - -## 0.1.0 - -### Minor Changes - -- chore: configure automated release workflow with changesets and GitHub Actions ([#168](https://github.com/godaddy/bento/pull/168) by @kbader-godaddy) diff --git a/packages/internal-props/LICENSE b/packages/internal-props/LICENSE deleted file mode 100644 index c0f0bb10b..000000000 --- a/packages/internal-props/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2025 GoDaddy Operating Company, LLC. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/internal-props/README.mdx b/packages/internal-props/README.mdx deleted file mode 100644 index eeb699a3a..000000000 --- a/packages/internal-props/README.mdx +++ /dev/null @@ -1,69 +0,0 @@ -import { Meta, Story, ArgTypes, Source, Controls } from '@storybook/addon-docs/blocks'; -import * as Stories from './internal-props.stories.tsx'; -import SourceDemo from './examples/override-classname.tsx?raw'; - - - -# InternalProps - -The `@bento/internal-props` package provides internal utilities and components used across the Bento project to bypass restrictions, filtering of props, or triggering of data-override props within the Bento ecosystem. This package is strictly for internal use by @bento-based components or those who use Bento to create design system components. - -> ⚠️ **Warning**: This package is not intended for public consumption and is subject to change without notice. It should only be used by internal Bento components or design system implementations. - -## Installation - -To install the package, use your preferred package manager: - -```shell -npm install @bento/internal-props -``` - -## API - -The package exports two main functions: - -### useInternalProps - -Extracts internal properties from a set of properties by removing the specified prefix. - -```tsx -import { useInternalProps } from '@bento/internal-props'; - -const [props, internal] = useInternalProps({ - '$$bento-internal-1-foo': 'bar', - '$$bento-internal-1-baz': 'qux', - regular: 'prop' -}); - -console.log(props); // { regular: 'prop' } -console.log(internal); // { foo: 'bar', baz: 'qux' } -``` - -The function accepts two arguments: -- `props`: The properties to extract from -- `prefix`: (Optional) The prefix to remove from the properties. Defaults to `$$bento-internal-{major}-` - -### toInternalProps - -Converts a set of properties to internal properties by prefixing them with the specified namespace. - -```tsx -import { toInternalProps } from '@bento/internal-props'; - -const internal = toInternalProps({ - foo: 'bar', - baz: 'qux' -}); - -console.log(internal); // { '$$bento-internal-1-foo': 'bar', '$$bento-internal-1-baz': 'qux' } -``` - -The function accepts two arguments: -- `props`: The properties to convert -- `prefix`: (Optional) The prefix to use for the internal properties. Defaults to `$$bento-internal-{major}-` - -### Example - - - - diff --git a/packages/internal-props/examples/override-classname.tsx b/packages/internal-props/examples/override-classname.tsx deleted file mode 100644 index 0fed137cb..000000000 --- a/packages/internal-props/examples/override-classname.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { toInternalProps } from '@bento/internal-props'; -import { useProps } from '@bento/use-props'; -import { withSlots } from '@bento/slots'; -/* v8 ignore next */ -import React from 'react'; - -/** - * Simple button component that accepts internal props. - * - * @param {Record} args - The component props. - * @returns {JSX.Element} The rendered button element. - * @public - */ -export const BentoButton = withSlots('InternalBentoButton', function ButtonComponent(args: Record) { - const { props, apply } = useProps(args); - - return ; -}); - -/** - * Example component demonstrating how to use toInternalProps for className overrides. - * - * @returns {JSX.Element} The rendered example with various button styles. - * @public - */ -export const Example = withSlots('ClassNameOverrideExample', function ExampleComponent() { - // Convert className to internal prop to avoid data-override - const primaryButtonProps = toInternalProps({ className: 'primary-button large-button' }); - - const customButtonProps = toInternalProps({ - className: ({ original }: { original: string }) => ['custom-button-class', original].join(' ') - }); - - return ( -
- {/* Regular button with default className */} - Default Button - - {/* Button with custom className that won't trigger data-override */} - Triggers data-override - - {/* Button with custom className that won't trigger data-override */} - Custom Styled Button - - {/* Button with multiple classNames */} - Primary Large Button -
- ); -}); diff --git a/packages/internal-props/internal-props.stories.tsx b/packages/internal-props/internal-props.stories.tsx deleted file mode 100644 index d4730fded..000000000 --- a/packages/internal-props/internal-props.stories.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { getMeta, getStory } from '@bento/storybook-addon-helpers'; -import { Example as OverrideClassNameExample } from './examples/override-classname'; - -export default getMeta({ - title: 'internal/internal-props' -}); - -export const Demo = getStory(OverrideClassNameExample); diff --git a/packages/internal-props/package.json b/packages/internal-props/package.json deleted file mode 100644 index e1ceb5f24..000000000 --- a/packages/internal-props/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "@bento/internal-props", - "version": "0.1.1", - "description": "Internal utilities for managing prefixed component properties", - "type": "module", - "main": "./dist/index.cjs", - "module": "./dist/index.js", - "scripts": { - "build": "tsup-node", - "dev": "tsup-node --watch", - "lint": "biome lint && tsc --noEmit", - "posttest": "npm run lint", - "prepublishOnly": "node ../../scripts/compile-readme.ts", - "pretest": "npm run build", - "test": "vitest --run", - "test:watch": "vitest" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/godaddy/bento.git" - }, - "keywords": [ - "bento", - "component", - "hook", - "internal", - "library", - "prefix", - "props", - "react" - ], - "author": "GoDaddy Operating Company, LLC", - "license": "MIT", - "bugs": { - "url": "https://github.com/godaddy/bento/issues" - }, - "homepage": "https://github.com/godaddy/bento#readme", - "files": [ - "dist", - "src", - "package.json" - ], - "peerDependencies": { - "react": "18.x || 19.x", - "react-dom": "18.x || 19.x" - }, - "exports": { - ".": { - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - } - }, - "./package.json": "./package.json" - }, - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org/" - } -} diff --git a/packages/internal-props/src/index.ts b/packages/internal-props/src/index.ts deleted file mode 100644 index f7d7de9a9..000000000 --- a/packages/internal-props/src/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -// -// Our build process introduces the version of the package as major, minor, and -// patch variables. -// -declare const major: string; -const namespace = ['$$bento', 'internal', major].filter(Boolean).join('-'); - -/** - * Extracts internal properties from a set of properties by removing the - * specified prefix. - * - * @param prefix - The prefix to remove from the properties. - * @param props - The properties to extract from. - * @returns A tuple containing the properties - * without the prefix and the internal properties with the prefix. - * @private - */ -function explode(prefix: string, props: Record): [Record, string[]] { - if (!prefix.endsWith('-')) prefix += '-'; - - const result: Record = {}; - const remove: string[] = []; - const keys = Object.keys(props); - - for (const key of keys) { - if (key.startsWith(prefix)) { - const newKey = key.slice(prefix.length); - - result[newKey] = props[key]; - remove.push(key); - } - } - - return [result, remove]; -} - -/** - * Extracts internal properties from a set of properties by removing the - * specified prefix. - * - * @param props - The properties to extract from. - * @param [prefix="$$bento-internal-{major}-"] - Optional prefix to remove from the properties. - * @returns A tuple containing the properties without the prefix and the internal properties with the prefix. - * @public - */ -export function useInternalProps( - props: Record, - prefix: string = namespace -): [Record, Record] { - const [internal, remove] = explode(prefix, props); - const result = { ...props }; - - for (const key of remove) { - delete result[key]; - } - - return [result, internal]; -} - -/** - * Converts a set of properties to internal properties by prefixing them with - * the specified namespace. - * - * @param props - The properties to convert. - * @param [prefix="$$bento-internal-{major}-"] - Optional prefix to use for the internal properties. - * @returns The converted properties with the prefix applied. - * @public - */ -export function toInternalProps(props: Record, prefix: string = namespace): Record { - if (!prefix.endsWith('-')) prefix += '-'; - - const result: Record = {}; - const keys = Object.keys(props); - - for (const key of keys) { - result[`${prefix}${key}`] = props[key]; - } - - return result; -} diff --git a/packages/internal-props/test/examples.browser.test.tsx b/packages/internal-props/test/examples.browser.test.tsx deleted file mode 100644 index 297274318..000000000 --- a/packages/internal-props/test/examples.browser.test.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Example } from '../examples/override-classname.tsx'; -import { render } from 'vitest-browser-react'; -import { describe, it } from 'vitest'; -import assume from 'assume'; -import React from 'react'; - -describe('@bento/internal-props examples', function bento() { - describe('ClassName Override Example', function classNameOverride() { - it('should render buttons with correct classNames', function test() { - const { container } = render(); - const buttons = container.querySelectorAll('button'); - - // Check default button - assume(buttons[0].className).equals('bento-button-base'); - assume(buttons[0].textContent).equals('Default Button'); - - // Check override trigger button - assume(buttons[1].className).equals('trigger-override'); - assume(buttons[1].textContent).equals('Triggers data-override'); - - // Check custom styled button - assume(buttons[2].className).equals('custom-button-class bento-button-base'); - assume(buttons[2].textContent).equals('Custom Styled Button'); - - // Check primary large button - assume(buttons[3].className).equals('primary-button large-button'); - assume(buttons[3].textContent).equals('Primary Large Button'); - }); - }); -}); diff --git a/packages/internal-props/test/internal.node.test.ts b/packages/internal-props/test/internal.node.test.ts deleted file mode 100644 index 11137e7e9..000000000 --- a/packages/internal-props/test/internal.node.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { useInternalProps, toInternalProps } from '@bento/internal-props'; -import pkg from '../package.json' with { type: 'json' }; -import { dirname, resolve, join } from 'node:path'; -import { fileURLToPath } from 'node:url'; -import { describe, it } from 'vitest'; -import fs from 'node:fs/promises'; -import assume from 'assume'; - -describe('@bento/internal-props', function internalPropsTests() { - const [major] = pkg.version.split('.'); - - describe('#useInternalProps', function useInternalPropsTests() { - it('should separate internal props based on the prefix', function separateInternalProps() { - const props = { - 'prefix-key1': 'value1', - 'prefix-key2': 'value2', - otherKey: 'value3' - }; - const prefix = 'prefix-'; - - const [result, internal] = useInternalProps(props, prefix); - - assume(result).eqls({ otherKey: 'value3' }); - assume(internal).eqls({ key1: 'value1', key2: 'value2' }); - }); - - it('should handle props without matching prefix', function handleNoMatchingPrefix() { - const props = { - otherKey: 'value1', - anotherKey: 'value2' - }; - const prefix = 'prefix-'; - - const [result, internal] = useInternalProps(props, prefix); - - assume(result).eqls(props); - assume(internal).eqls({}); - }); - - it('should add a dash to the prefix if it does not end with one', function addDashToPrefix() { - const props = { - 'prefix-key1': 'value1', - 'prefix-key2': 'value2' - }; - const prefix = 'prefix'; - - const [result, internal] = useInternalProps(props, prefix); - - assume(result).eqls({}); - assume(internal).eqls({ key1: 'value1', key2: 'value2' }); - }); - - it('should handle empty props', function handleEmptyProps() { - const props = {}; - const prefix = 'prefix-'; - - const [result, internal] = useInternalProps(props, prefix); - - assume(result).eqls({}); - assume(internal).eqls({}); - }); - - it('should apply the default prefix if none is provided', function applyDefaultPrefix() { - const props = { - [`$$bento-internal-${major}-key1`]: 'value1', - [`$$bento-internal-${major}-key2`]: 'value2' - }; - - const [result, internal] = useInternalProps(props); - - assume(result).eqls({}); - assume(internal).eqls({ key1: 'value1', key2: 'value2' }); - }); - }); - - describe('#toInternalProps', function toInternalPropsTests() { - it('should prefix all keys with the given prefix', function prefixAllKeys() { - const props = { - key1: 'value1', - key2: 'value2' - }; - const prefix = 'prefix-'; - - const result = toInternalProps(props, prefix); - - assume(result).eqls({ - 'prefix-key1': 'value1', - 'prefix-key2': 'value2' - }); - }); - - it('should add a dash to the prefix if it does not end with one', function addDashToPrefixInToInternalProps() { - const props = { - key1: 'value1', - key2: 'value2' - }; - const prefix = 'prefix'; - - const result = toInternalProps(props, prefix); - - assume(result).eqls({ - 'prefix-key1': 'value1', - 'prefix-key2': 'value2' - }); - }); - - it('should handle empty props', function handleEmptyProps() { - const props = {}; - const prefix = 'prefix-'; - - const result = toInternalProps(props, prefix); - - assume(result).eqls({}); - }); - - it('applies the default prefix if none is provided', function applyDefaultPrefix() { - const props = { - key1: 'value1', - key2: 'value2' - }; - - const result = toInternalProps(props); - - assume(result).eqls({ - [`$$bento-internal-${major}-key1`]: 'value1', - [`$$bento-internal-${major}-key2`]: 'value2' - }); - }); - }); - - describe('Public API', function packageSuite() { - const __dirname = dirname(fileURLToPath(import.meta.url)); - - describe('#exports', function exportsSuite() { - Object.keys(pkg.exports).forEach(function each(subpaths) { - describe(`${subpaths}`, function subpathsSuite() { - const exportPath = (pkg.exports as any)[subpaths]; - - if (typeof exportPath === 'string') { - return it(`exports ${subpaths} exists`, async function exportedTest() { - const path = resolve(__dirname, '..', exportPath); - await fs.access(path, fs.constants.F_OK); - }); - } - - Object.keys(exportPath).forEach(function each(exported) { - Object.keys(exportPath[exported]).forEach(function each(key) { - it(`conditional export "${exported}.${key}" exists for ${join(pkg.name, subpaths)}`, async function exportedTest() { - const path = resolve(__dirname, '..', exportPath[exported][key]); - await fs.access(path, fs.constants.F_OK); - }); - }); - }); - }); - }); - }); - }); -}); diff --git a/packages/internal-props/tsconfig.json b/packages/internal-props/tsconfig.json deleted file mode 100644 index aabb3e399..000000000 --- a/packages/internal-props/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../configs/tsconfig.json", - "include": ["./src", "./test", "./examples"], - "compilerOptions": { - "rootDir": "./", - "declarationDir": "./dist" - } -} diff --git a/packages/internal-props/tsup.config.ts b/packages/internal-props/tsup.config.ts deleted file mode 100644 index 817a487e1..000000000 --- a/packages/internal-props/tsup.config.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { shared } from '../../configs/tsup.config.mjs'; -import { version } from './package.json'; -import { defineConfig } from 'tsup'; - -export default defineConfig({ - ...shared, - entry: ['src/index.ts'], - - /** - * Introduces the version of the package as a define variable in the build, - * allowing the code to reference major, minor, and patch versions numbers. - * - * @param {import('esbuild').BuildOptions} options - The options object passed to esbuild. - * @returns {void} - * @private - */ - esbuildOptions(options) { - // - // Package versions can include prerelease tags (e.g. 1.2.3-alpha) or build metadata - // (e.g. 1.2.3+20230315). We only want the core version numbers for build-time - // constants, so we use regex to extract just the major.minor.patch parts. - // - // @see https://semver.org/ - // - const versionMatch = version.match(/^(\d+)\.(\d+)\.(\d+)/); - const semver = versionMatch ? versionMatch.slice(1) : ['0', '0', '0']; - - options.define ??= {}; - ['major', 'minor', 'patch'].forEach(function defineVersion(key, index) { - options.define[key] = JSON.stringify(semver[index]); - }); - } -}); diff --git a/packages/internal-props/vitest.config.ts b/packages/internal-props/vitest.config.ts deleted file mode 100644 index 3ca0424fa..000000000 --- a/packages/internal-props/vitest.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import sharedConfig, { ssr, browser } from '../../configs/vitest.config.mts'; -import { defineConfig, mergeConfig } from 'vitest/config'; - -export default mergeConfig( - sharedConfig, - defineConfig({ - test: { - projects: [ssr, browser] - } - }) -); diff --git a/packages/portal/test/__snapshots__/examples.browser.test.tsx.snap b/packages/portal/test/__snapshots__/examples.browser.test.tsx.snap new file mode 100644 index 000000000..28f0393df --- /dev/null +++ b/packages/portal/test/__snapshots__/examples.browser.test.tsx.snap @@ -0,0 +1,7 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`@bento/portal examples > BasicExample > renders basic portal example 1`] = `"
Portal content
"`; + +exports[`@bento/portal examples > CustomContainerExample > renders custom container example 1`] = `"
Custom container content
"`; + +exports[`@bento/portal examples > PortalProviderExample > renders portal provider example 1`] = `"
Portal content using PortalProviderContainer: Custom via PortalProvider
"`; diff --git a/packages/portal/test/examples.browser.test.tsx b/packages/portal/test/examples.browser.test.tsx index 40c38cfde..9f281cc95 100644 --- a/packages/portal/test/examples.browser.test.tsx +++ b/packages/portal/test/examples.browser.test.tsx @@ -1,5 +1,5 @@ import { render } from 'vitest-browser-react'; -import { describe, it } from 'vitest'; +import { describe, it, expect } from 'vitest'; import React from 'react'; import assume from 'assume'; import { BasicExample } from '../examples/basic.tsx'; @@ -19,10 +19,7 @@ describe('@bento/portal examples', function bento() { assume(portalContent?.getAttribute('data-portal')).equals('true'); assume(portalContent?.getAttribute('data-mounted')).equals('true'); - // DOM snapshot - shows data attributes on Container with Text child - assume(portalContent?.outerHTML).equals( - '
Portal content
' - ); + expect(portalContent?.outerHTML).toMatchSnapshot(); }); }); @@ -40,10 +37,7 @@ describe('@bento/portal examples', function bento() { assume(content?.getAttribute('data-portal')).equals('true'); assume(content?.getAttribute('data-mounted')).equals('true'); - // DOM snapshot - shows data attributes on Container rendered to custom container - assume(content?.outerHTML).equals( - '
Custom container content
' - ); + expect(content?.outerHTML).toMatchSnapshot(); }); }); @@ -59,10 +53,7 @@ describe('@bento/portal examples', function bento() { assume(portalContent?.getAttribute('data-portal')).equals('true'); assume(portalContent?.getAttribute('data-mounted')).equals('true'); - // DOM snapshot - shows data attributes on Container with Text children - assume(portalContent?.outerHTML).equals( - '
Portal content using PortalProviderContainer: Custom via PortalProvider
' - ); + expect(portalContent?.outerHTML).toMatchSnapshot(); }); }); }); diff --git a/packages/pressable/test/pressable.node.test.tsx b/packages/pressable/test/pressable.node.test.tsx index 7d082d5b7..b968cc5e4 100644 --- a/packages/pressable/test/pressable.node.test.tsx +++ b/packages/pressable/test/pressable.node.test.tsx @@ -29,24 +29,6 @@ describe('@bento/pressable', function bento() { assume(result).match(/^]*>Press me<\/div>$/); }); - describe('#slots', function slots() { - it('renders correct [data-override] attribute values', function overrides() { - const result = renderToStringPressable({ - className: 'custom-class', - style: { color: 'red' }, - children:
Press me
, - onClick: () => void 0, - onPress: () => void 0, - onPressStart: () => void 0, - onPressEnd: () => void 0, - onPressUp: () => void 0, - onPressChange: () => void 0 - }); - - assume(result).includes('data-override="className style"'); - }); - }); - describe('Public API', function packageSuite() { const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/slots/src/override.ts b/packages/slots/src/override.ts index bb12e6b24..240856c11 100644 --- a/packages/slots/src/override.ts +++ b/packages/slots/src/override.ts @@ -45,10 +45,10 @@ interface OverrideResult { }; } -const triggers: string[] = ['className', 'style']; - /** * Overrides the properties of a given context based on certain conditions. + * When the environment is locked, only flags slots that were added before + * the lock boundary (have a lower lockGeneration). * * @param args.context - The context object. * @param args.props - The properties object. @@ -60,35 +60,62 @@ export function override>({ props }: OverrideArgs): OverrideResult | undefined { const causes: string[] = []; - const { namespace, assigned, override } = context.slots; - const slot: Record | undefined = assigned[namespace.join('.')]; + const { namespace, assigned, override: overrideFlag } = context.slots; + const currentNamespace = namespace.join('.'); + const slot: Record | undefined = assigned[currentNamespace]; + + // + // Data override is only supported when the environment is locked. + // + if (!(context.env?.locked ?? false)) return; + + const currentLockGeneration = context.env?.lockGeneration ?? 0; + // + // Get slot generation for this namespace. Default to current generation if not tracked. + // + const slotGeneration = context.slots?.slotGenerations?.[currentNamespace] ?? currentLockGeneration; + const isEarlierGeneration = slotGeneration < currentLockGeneration; if (typeof props['data-override'] === 'string') { causes.push(...props['data-override'].split(' ')); } - if (override && !causes.includes('context')) causes.push('context'); - if ('className' in props && !causes.includes('className')) causes.push('className'); + if (overrideFlag && !causes.includes('context')) causes.push('context'); // - // For style we need to take a more sophisticated approach, users are allowed - // to define CSS variables in the style prop, so we need to check if the keys - // are prefixed with `--` or not. + // Only flag className/style if they came from a slot assignment (exist in the slot object) + // AND the slot is from an earlier generation. Props that are only in `props` (not from slots) + // might be from the component's own render (e.g., CSS modules) and shouldn't be flagged. // - if ('style' in props && !causes.includes('style')) { - const style = props.style as CSSProperties; - const keys = Object.keys(style); + if (slot && isEarlierGeneration) { + let hasFlaggableChanges = false; - if (keys.some((key) => !isCSSVariable(key))) { - causes.push('style'); + if ('className' in slot && !causes.includes('className')) { + causes.push('className'); + hasFlaggableChanges = true; + } + + if ('style' in slot && !causes.includes('style')) { + const style = slot.style as CSSProperties; + const keys = Object.keys(style); + const hasNonCSSVariables = keys.some((key) => !isCSSVariable(key)); + + if (hasNonCSSVariables) { + causes.push('style'); + hasFlaggableChanges = true; + } } - } - if (slot) { - Object.keys(slot).forEach(function forEach(name) { - if (triggers.includes(name) && !causes.includes(name)) causes.push(name); - if (!causes.includes('slot')) causes.push('slot'); - }); + // Check for other slot modifications (not className/style/children which are handled separately) + const slotKeys = Object.keys(slot).filter((key) => !['className', 'style'].includes(key)); + if (slotKeys.length > 0) { + hasFlaggableChanges = true; + } + + // Only add 'slot' if there are actual modifications worth flagging + if (hasFlaggableChanges && !causes.includes('slot')) { + causes.push('slot'); + } } if (!causes.length) return; diff --git a/packages/slots/src/replace.ts b/packages/slots/src/replace.ts index b0d9ea278..e91c1ef42 100644 --- a/packages/slots/src/replace.ts +++ b/packages/slots/src/replace.ts @@ -64,15 +64,44 @@ export function replace>({ props, name, contex override: !!target } }, - props: {} + props: undefined as Record | undefined, + Component: undefined as ComponentType | undefined } as any; + if (isPropsOverride(target)) result.props = { ...target.props }; + else result.Component = target; + + const locked = context.env?.locked ?? false; + if (!locked) return result; + const causes = (props['data-override'] || '').split(' ').filter(Boolean); if (!causes.includes('context')) causes.push('context'); - result.props = useDataAttributes({ override: causes }); - if (isPropsOverride(target)) result.props = { ...target.props }; - else result.Component = target; + // Merge props from original and override target for override detection + const mergedProps = isPropsOverride(target) ? { ...props, ...target.props } : props; + + // Check for className and style overrides in the merged props + if ('className' in mergedProps && !causes.includes('className')) { + causes.push('className'); + } + if ('style' in mergedProps && !causes.includes('style')) { + // Check if style contains non-CSS-variable properties + const styleKeys = Object.keys(mergedProps.style || {}); + const hasNonCSSVariables = styleKeys.some((key) => !key.startsWith('--')); + if (hasNonCSSVariables) { + causes.push('style'); + } + } + + const overrideProps = useDataAttributes({ override: causes }); + if (isPropsOverride(target)) { + result.props = { + ...overrideProps, + ...result.props + }; + } else { + result.props = overrideProps; + } return result; } diff --git a/packages/slots/src/slots.tsx b/packages/slots/src/slots.tsx index 82b2a9726..e046cc1f3 100644 --- a/packages/slots/src/slots.tsx +++ b/packages/slots/src/slots.tsx @@ -81,6 +81,7 @@ export function withSlots( const currentNamespace = ctx.slots.namespace.join('.'); const inheritedSlots: Record = {}; + const inheritedGenerations: Record = {}; const prefix = `${currentNamespace}.`; // @@ -91,17 +92,36 @@ export function withSlots( for (const key in ctx.slots.assigned) { if (currentNamespace === '' && !key.includes('.')) { inheritedSlots[key] = ctx.slots.assigned[key]; + if (ctx.slots.slotGenerations && key in ctx.slots.slotGenerations) { + inheritedGenerations[key] = ctx.slots.slotGenerations[key]; + } } else if (key === currentNamespace || key.startsWith(prefix)) { inheritedSlots[key] = ctx.slots.assigned[key]; + if (ctx.slots.slotGenerations && key in ctx.slots.slotGenerations) { + inheritedGenerations[key] = ctx.slots.slotGenerations[key]; + } } } ctx.slots.assigned = inheritedSlots; + ctx.slots.slotGenerations = inheritedGenerations; // // merge the new slots with the assigned slots, // parent component slots should take precedence over child ones. // + const currentGeneration = ctx.env.lockGeneration || 0; + // + // Slots passed via props at this point are part of the CURRENT render tree. + // If we're inside a locked environment, these are "internal composition" slots + // and should be tagged with the CURRENT generation (not flagged as overrides). + // + // Consumer slots (passed from OUTSIDE the lock) are tagged by the Environment + // component BEFORE it increments the generation, so they have a lower generation + // and will be flagged as overrides. + // + const slotPropsGeneration = currentGeneration; + for (const slotKey in slots) { // Build the fully qualified slot key by prefixing with current namespace const namespacedKey = ctx.slots.namespace.length > 0 ? `${currentNamespace}.${slotKey}` : slotKey; @@ -114,8 +134,17 @@ export function withSlots( // if (!assignedSlot) { ctx.slots.assigned[namespacedKey] = newSlot; + // Tag new slot with generation from props (before current component) + ctx.slots.slotGenerations[namespacedKey] = slotPropsGeneration; } else if (typeof assignedSlot === 'object') { ctx.slots.assigned[namespacedKey] = { ...newSlot, ...assignedSlot }; + // Keep the earliest (lowest) generation when merging + // If the slot doesn't have a generation yet, use props generation + if (!(namespacedKey in ctx.slots.slotGenerations)) { + ctx.slots.slotGenerations[namespacedKey] = slotPropsGeneration; + } + // If newSlot is from an earlier generation (consumer slot), update the tag + // We assume parent slots (assignedSlot) are from consumer, so keep their generation } else if (typeof assignedSlot === 'function') { const existingPrevious = assignedSlot.__slotPrevious || []; const newPrevious = [newSlot, ...existingPrevious]; @@ -125,6 +154,11 @@ export function withSlots( mergedFnSlot.__slotPrevious = newPrevious; ctx.slots.assigned[namespacedKey] = mergedFnSlot; + // For functions, keep the parent function's generation (it takes precedence) + ctx.slots.slotGenerations = ctx.slots.slotGenerations || {}; + if (!(namespacedKey in ctx.slots.slotGenerations)) { + ctx.slots.slotGenerations[namespacedKey] = slotPropsGeneration; + } } } diff --git a/packages/slots/test/__snapshots__/examples.browser.test.tsx.snap b/packages/slots/test/__snapshots__/examples.browser.test.tsx.snap new file mode 100644 index 000000000..474866f3b --- /dev/null +++ b/packages/slots/test/__snapshots__/examples.browser.test.tsx.snap @@ -0,0 +1,21 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`@bento/slots examples > Button > should render a button 1`] = `""`; + +exports[`@bento/slots examples > Memo > should render a memoized component 1`] = `"
"`; + +exports[`@bento/slots examples > Merged > should render a component with the correct merged slots 1`] = `"

Description: Merged summaryBetter errorExpect class "merged-class", id "merged" and title "better-title".

"`; + +exports[`@bento/slots examples > MergedFunction > should render all enhancement levels in correct order 1`] = `"
First Enhancement
Second Enhancement
Third Enhancement: merged-fn
"`; + +exports[`@bento/slots examples > Namespace > should allow children to inherit root-level slots 1`] = `"
Content
"`; + +exports[`@bento/slots examples > Namespace > should render a component with correct replacements 1`] = `""`; + +exports[`@bento/slots examples > Namespace > should render a component with correct slot names 1`] = `""`; + +exports[`@bento/slots examples > Namespace > should render a component with slots 1`] = `""`; + +exports[`@bento/slots examples > SlotFunction > should render a slot function override 1`] = `"
"`; + +exports[`@bento/slots examples > SlotProps > should render a component with slot props, creating a red button 1`] = `"
"`; diff --git a/packages/slots/test/examples.browser.test.tsx b/packages/slots/test/examples.browser.test.tsx index a3a58fca5..924910826 100644 --- a/packages/slots/test/examples.browser.test.tsx +++ b/packages/slots/test/examples.browser.test.tsx @@ -12,7 +12,7 @@ import { NamespaceWithReplacements, NamespaceRootLevelInheritance } from '../examples/namespace.tsx'; -import { describe, it } from 'vitest'; +import { describe, it, expect } from 'vitest'; import assume from 'assume'; import React from 'react'; @@ -20,16 +20,13 @@ describe('@bento/slots examples', function bento() { describe('Button', function button() { it('should render a button', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals(''); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('Memo', function memo() { it('should render a memoized component', async function test() { const screen = render(); - const result = screen.container.innerHTML; const logger = console.log; let logs: any[] = []; @@ -37,9 +34,7 @@ describe('@bento/slots examples', function bento() { logs = args; }; - assume(result).equals( - '
' - ); + expect(screen.container.innerHTML).toMatchSnapshot(); await screen.getByRole('button', { name: 'Click me' }).click(); console.log = logger; @@ -53,18 +48,13 @@ describe('@bento/slots examples', function bento() { describe('SlotFunction', function slotfn() { it('should render a slot function override', function slotted() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - '
' - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('SlotProps', function slotprops() { it('should render a component with slot props, creating a red button', async function props() { const screen = render(); - const result = screen.container.innerHTML; const logger = console.log; let logs: any[] = []; @@ -72,9 +62,7 @@ describe('@bento/slots examples', function bento() { logs = args; }; - assume(result).equals( - '
' - ); + expect(screen.container.innerHTML).toMatchSnapshot(); await screen.getByRole('button', { name: 'Click me' }).click(); console.log = logger; @@ -87,82 +75,36 @@ describe('@bento/slots examples', function bento() { describe('Merged', function merged() { it('should render a component with the correct merged slots', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - [ - '

', - ' Description: ', - ' ', - ' Merged summary', - ' Better error', - ' Expect class "merged-class", id "merged" and title "better-title".', - '

' - ] - .join('\n') - .replace(/^\s+/gm, '') - .replace(/\n/g, '') - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('MergedFunction', function mergedFunction() { it('should render all enhancement levels in correct order', function allLevels() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - '
' + - '
First Enhancement
' + - '
Second Enhancement
' + - '
Third Enhancement: merged-fn
' + - '
' - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('Namespace', function namespace() { it('should render a component with slots', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - '' + - '' - ); + expect(container.innerHTML).toMatchSnapshot(); }); it('should render a component with correct slot names', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - '' + - '' - ); + expect(container.innerHTML).toMatchSnapshot(); }); it('should render a component with correct replacements', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).equals( - '' + - '' - ); + expect(container.innerHTML).toMatchSnapshot(); }); it('should allow children to inherit root-level slots', function test() { const { container } = render(); - const result = container.innerHTML; - - console.log('bbbb', result); - - assume(result).equals( - '
' + - 'Content
' - ); + expect(container.innerHTML).toMatchSnapshot(); }); }); diff --git a/packages/slots/test/override.node.test.ts b/packages/slots/test/override.node.test.ts index 4713f7e22..23cddd493 100644 --- a/packages/slots/test/override.node.test.ts +++ b/packages/slots/test/override.node.test.ts @@ -3,15 +3,23 @@ import { renderToString } from 'react-dom/server'; import { withSlots } from '@bento/slots'; import { describe, it } from 'vitest'; import { Box, defaults } from '@bento/box'; +import { Environment } from '@bento/environment'; +import { useProps } from '@bento/use-props'; import assume from 'assume'; import React from 'react'; describe('@bento/slots override', function bento() { - function createComponent(name: string, props = {}, slots = {}, components = {}) { + function createComponent(name: string, props = {}, slots = {}, components = {}, locked = false) { const TestReturn = withSlots(`BentoOverride-${name}`, function Component(args: any) { return React.createElement('div', { ...args }); }); + if (locked) { + // When locked, just pass slots directly to the component via the slots prop + const child = React.createElement(TestReturn, { slot: 'test', slots: { test: slots }, ...props }); + return renderToString(React.createElement(Environment, { lock: true, components, children: child })); + } + const value = defaults(); value.slots.assigned = { test: slots }; value.env.components = components; @@ -25,114 +33,390 @@ describe('@bento/slots override', function bento() { assume(override).is.a('function'); }); - it('does not introduce data-override by default', function noOverride() { - const html = createComponent('noOverride', { id: 'example', role: 'presentation' }); - assume(html).contains(''); - }); + describe('default behavior (no locked Environment)', function defaultBehavior() { + it('does not introduce data-override by default', function noOverride() { + const html = createComponent('noOverride', { id: 'example', role: 'presentation' }); + // data-slot="test" is added for slotted components (from main) + assume(html).contains(''); + assume(html).does.not.contain('data-override'); + }); - it('introduces data-override when style is present', function style() { - const html = createComponent('style', { style: { color: 'red' } }); - assume(html).contains('
'); - }); + it('does not add data-override when style is present', function style() { + const html = createComponent('style', { style: { color: 'red' } }); + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); - it('does not introduce a data-override when CSS variables are introduced', function cssVariables() { - const html = createComponent('cssVariables', { style: { '--color': 'red' } }); - assume(html).contains('
'); - }); + it('does not introduce data-override for CSS variables', function cssVariables() { + const html = createComponent('cssVariables', { style: { '--color': 'red' } }); + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); - it('introduces data-override when CSS variables and another style property are present', function cssVariablesAndStyle() { - const html = createComponent('cssVariablesAndStyle', { style: { '--color': 'red', color: 'blue' } }); - assume(html).contains('
'); - }); + it('does not add data-override when CSS variables and style are present', function cssVariablesAndStyle() { + const html = createComponent('cssVariablesAndStyle', { style: { '--color': 'red', color: 'blue' } }); + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); - it('introduces data-override when className is present', function className() { - const html = createComponent('className', { className: 'example' }); - assume(html).contains('
'); - }); + it('does not introduce data-override when className is present', function className() { + const html = createComponent('className', { className: 'example' }); + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); - it('adds to an existing data-override', function existing() { - const html = createComponent('existing', { style: { color: 'red' }, 'data-override': 'boink' }); - assume(html).contains('
'); - }); + it('does not introduce data-override when existing data-override is present', function existing() { + const html = createComponent('existing', { style: { color: 'red' }, 'data-override': 'boink' }); + assume(html).contains('
'); + }); + + it('does not add data-override for multiple style triggers', function multiple() { + const html = createComponent('multiple', { + style: { color: 'red' }, + className: 'example' + }); - it('separates multiple causes with a space', function multiple() { - const html = createComponent('multiple', { - style: { color: 'red' }, - className: 'example' + assume(html).contains('
'); + assume(html).does.not.contain('data-override="'); }); - assume(html).contains( - '
' - ); + it('does not introduce data-override when a slot override is used', function slot() { + const html = createComponent( + 'slot', + {}, + { + style: { color: 'red' } + } + ); + + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); + + it('does not introduce data-override when a component is replaced through Slot.Context', function context() { + const html = createComponent( + 'context', + { + style: { color: 'red' } + }, + {}, + { + 'BentoOverride-context': function Component(props: any) { + assume(props['data-override']).equals(undefined); + return React.createElement('div', props); + } + } + ); + + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); }); - it('introduces data-override when a slot override is used', function slot() { - const html = createComponent( - 'slot', - {}, - { - style: { color: 'red' } - } - ); + describe('locked Environment behavior', function lockedBehavior() { + it('introduces data-override when style is present via slot in locked environment', function styleWithLock() { + // Style must be passed via slots (not direct props) to trigger override detection + const InnerComponent = withSlots('StyleLockInner', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedComponent = withSlots('StyleLockOuter', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + // Pass style via slots prop to trigger slot-based override detection + const html = renderToString( + React.createElement(LockedComponent, { slots: { test: { style: { color: 'red' } } } }) + ); + + assume(html).contains('data-override'); + assume(html).contains('style'); + assume(html).contains('data-slot="test"'); + }); + + it('introduces data-override when className is present via slot in locked environment', function classNameWithLock() { + const InnerComponent = withSlots('ClassLockInner', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedComponent = withSlots('ClassLockOuter', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + // Pass className via slots prop to trigger slot-based override detection + const html = renderToString(React.createElement(LockedComponent, { slots: { test: { className: 'example' } } })); + + assume(html).contains('data-override'); + assume(html).contains('className'); + assume(html).contains('data-slot="test"'); + }); + + it('does not introduce data-override for CSS variables in locked environment', function cssVariablesLocked() { + const InnerComponent = withSlots('CSSVarLockInner', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedComponent = withSlots('CSSVarLockOuter', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + const html = renderToString( + React.createElement(LockedComponent, { slots: { test: { style: { '--color': 'red' } } } }) + ); + + // CSS-variable-only style should NOT trigger data-override + assume(html).contains('style="--color:red"'); + assume(html).contains('data-slot="test"'); + assume(html).does.not.contain('data-override'); + }); + + it('separates multiple causes with a space in locked environment', function multipleLocked() { + const InnerComponent = withSlots('MultipleLockInner', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedComponent = withSlots('MultipleLockOuter', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); - assume(html).contains('
'); + const html = renderToString( + React.createElement(LockedComponent, { + slots: { + test: { + style: { color: 'red' }, + className: 'example' + } + } + }) + ); + + assume(html).contains('data-override="className style slot"'); + assume(html).contains('data-slot="test"'); + }); }); - it('introduces data-override when a component is replaced through Slot.Context', function context() { - const html = createComponent( - 'context', - { - style: { color: 'red' } - }, - {}, - { - 'BentoOverride-context': function Component(props: any) { - assume(props['data-override']).equals('context style'); - return React.createElement('div', props); + describe('parent component override inheritance', function parentTests() { + it('does not inherit context override without locked environment', function parentNoLock() { + const Kiddo = withSlots(`BentoOverride-Kiddo`, function Component(args: any) { + return React.createElement('p', args, args.children); + }); + + const Parent = withSlots(`BentoOverride-Parent`, function Component(args) { + return React.createElement( + 'section', + args, + React.createElement( + Kiddo, + { + id: 'example', + slot: 'kiddo' + }, + 'Hello World' + ) + ); + }); + + const value = defaults(); + value.env.components = { + 'BentoOverride-Parent': function Parent(props) { + assume(props['data-override']).equals(undefined); + return React.createElement('div', null, React.createElement(Kiddo, null, 'No data-override')); } - } - ); + }; + + const html = renderToString(React.createElement(Box.Provider, { value }, React.createElement(Parent))); + + assume(html).equals('

No data-override

'); + }); + + it('inherits context override when environment is locked', function parentWithLock() { + const Kiddo = withSlots(`BentoOverride-KiddoLocked`, function Component(args: any) { + return React.createElement('p', args, args.children); + }); + + const Parent = withSlots(`BentoOverride-ParentLocked`, function Component(args) { + return React.createElement( + 'section', + args, + React.createElement( + Kiddo, + { + id: 'example', + slot: 'kiddo' + }, + 'Hello World' + ) + ); + }); - assume(html).contains('
'); + const value = defaults(); + value.env.locked = true; + value.env.lockGeneration = 1; + value.env.components = { + 'BentoOverride-ParentLocked': function Parent(props) { + assume(props['data-override']).equals('context'); + return React.createElement('div', null, React.createElement(Kiddo, null, 'Should have data-override')); + } + }; + + const html = renderToString(React.createElement(Box.Provider, { value }, React.createElement(Parent))); + + assume(html).equals('

Should have data-override

'); + }); }); - it('inherits the context override from the parent component', function parent() { - const Kiddo = withSlots(`BentoOverride-Kiddo`, function Component(args: any) { - return React.createElement('p', args, args.children); - }); - - const Parent = withSlots(`BentoOverride-Parent`, function Component(args) { - return React.createElement( - 'section', - args, - React.createElement( - Kiddo, - { - id: 'example', - slot: 'kiddo' - }, - 'Hello World' - ) + describe('lock-based override detection', function lockBasedOverrides() { + it('flags className when passed via slots to component inside locked environment', function lockedSameGen() { + const TestComponent = withSlots('LockSameGen', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + // Wrap in a design system component pattern: slots are passed from outside the lock + const DesignSystemComponent = withSlots('LockSameGenDesign', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(TestComponent, { ...props, slot: 'test' }) + }); + }); + + // Pass className via slots from the "consumer" (before lock) + const html = renderToString( + React.createElement(DesignSystemComponent, { + slots: { test: { className: 'internal' } } + }) ); + + // SHOULD have data-override since className is passed via slot from outside the lock + assume(html).contains('data-override'); + assume(html).contains('className'); + assume(html).contains('class="internal"'); }); - const value = defaults(); - value.env.components = { - 'BentoOverride-Parent': function Parent(props) { - assume(props['data-override']).equals('context'); - - // - // It is intentional that we are not passing down the props into - // the created element below, this is to simulate if someone - // would remove the props from the component. A child component - // should still be able to indicate that a parent was overridden. - // - return React.createElement('div', null, React.createElement(Kiddo, null, 'Should have data-override')); - } - }; - - const html = renderToString(React.createElement(Box.Provider, { value }, React.createElement(Parent))); - - assume(html).equals('

Should have data-override

'); + it('flags className when environment is locked and slot is from earlier generation', function lockedEarlierGen() { + const InnerComponent = withSlots('LockEarlierGen', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedDesignComponent = withSlots('LockEarlierGenDesign', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + const html = renderToString( + React.createElement(Environment, { + children: React.createElement(LockedDesignComponent, { + slots: { + test: { className: 'consumer' } + } + }) + }) + ); + + // SHOULD have data-override since it's from earlier generation (consumer modification) + assume(html).contains('data-override="className slot"'); + assume(html).contains('class="consumer"'); + assume(html).contains('data-slot="test"'); + }); + + it('flags slot modifications from earlier generation even without className or style', function slotOnly() { + const InnerComponent = withSlots('LockSlotOnly', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedDesignComponent = withSlots('LockSlotOnlyDesign', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + const html = renderToString( + React.createElement(Environment, { + children: React.createElement(LockedDesignComponent, { + slots: { + test: { children: 'Hello' } + } + }) + }) + ); + + assume(html).contains('
Hello
'); + }); + + it('does not flag slots when not locked', function notLocked() { + const InnerComponent = withSlots('NotLocked', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const Component = withSlots('NotLockedDesign', function Component(props: any) { + return React.createElement(InnerComponent, { ...props, slot: 'test' }); + }); + + const html = renderToString( + React.createElement(Environment, { + children: React.createElement(Component, { + slots: { + test: { className: 'test', style: { color: 'red' } } + } + }) + }) + ); + + // Without lock, no data-override should be added + assume(html).contains('class="test"'); + assume(html).contains('style="color:red"'); + assume(html).contains('data-slot="test"'); + assume(html).does.not.contain('data-override'); + }); + + it('flags style modifications from earlier generation when locked', function lockedStyleEarlier() { + const InnerComponent = withSlots('LockStyleEarlier', function Component(args: any) { + const { props } = useProps(args); + return React.createElement('div', props); + }); + + const LockedDesignComponent = withSlots('LockStyleEarlierDesign', function Component(props: any) { + return React.createElement(Environment, { + lock: true, + children: React.createElement(InnerComponent, { ...props, slot: 'test' }) + }); + }); + + const html = renderToString( + React.createElement(Environment, { + children: React.createElement(LockedDesignComponent, { + slots: { + test: { style: { color: 'blue' } } + } + }) + }) + ); + + assume(html).contains('data-override="style slot"'); + assume(html).contains('style="color:blue"'); + assume(html).contains('data-slot="test"'); + }); }); }); diff --git a/packages/slots/test/replace.node.test.ts b/packages/slots/test/replace.node.test.ts index 40e550e62..a466869c6 100644 --- a/packages/slots/test/replace.node.test.ts +++ b/packages/slots/test/replace.node.test.ts @@ -3,91 +3,214 @@ import { describe, it } from 'vitest'; import assume from 'assume'; import { renderToString } from 'react-dom/server'; import { withSlots } from '@bento/slots'; -import { Box, defaults } from '@bento/box'; +import { Environment } from '@bento/environment'; import React from 'react'; describe('@bento/slots replace', function bento() { - function createComponent(name: string, props = {}, slots = {}, components = {}) { + function renderWithEnvironment( + name: string, + props: Record, + components: Record, + lock: boolean + ) { const TestReturn = withSlots(`BentoReplace-${name}`, function Component(args: any) { return React.createElement('div', { ...args }); }); - const value = defaults(); - value.slots.assigned = { test: slots }; - value.env.components = components; + const child = React.createElement(TestReturn, { slot: 'test', ...props }); - return renderToString( - React.createElement(Box.Provider, { value }, React.createElement(TestReturn, { slot: 'test', ...props })) - ); + return renderToString(React.createElement(Environment, { lock, components, children: child })); + } + + function renderWithoutEnvironment(name: string, props: Record) { + const TestReturn = withSlots(`BentoReplace-${name}`, function Component(args: any) { + return React.createElement('div', { ...args }); + }); + + return renderToString(React.createElement(TestReturn, { slot: 'test', ...props })); } it('exposes the function', function exposes() { assume(replace).is.a('function'); }); - it('introduces data-override with context when component is replaced', function componentReplacement() { - const html = createComponent( - 'componentReplacement', - { id: 'example' }, - {}, - { - 'BentoReplace-componentReplacement': function Component(props: any) { - assume(props['data-override']).equals('context'); - return React.createElement('div', props); - } - } - ); - - assume(html).contains('
'); + describe('default behavior (no Environment component)', function defaultBehavior() { + it('renders without data-override attributes by default', function noDataOverride() { + const html = renderWithoutEnvironment('noDataOverride', { id: 'example', className: 'test-class' }); + + assume(html).contains(''); + assume(html).does.not.contain('data-override'); + }); + + it('flags context with data-override when Environment is locked', function lockedWithOverride() { + const html = renderWithEnvironment( + 'componentReplacement-locked', + { id: 'example' }, + { + 'BentoReplace-componentReplacement-locked': function Component(props: any) { + assume(props['data-override']).equals('context'); + return React.createElement('div', props); + } + }, + true + ); + + assume(html).contains('
'); + }); }); - it('allows props to be overridden through component replacement', function propsOverride() { - const html = createComponent( - 'propsOverride', - { id: 'original' }, - {}, - { - 'BentoReplace-propsOverride': { - props: { - id: 'overridden', - className: 'custom-class' + describe('props-based overrides', function propsOverride() { + it('renders props override without data-override when unlocked', function unlockedPropsOverride() { + const html = renderWithEnvironment( + 'propsOverride-unlocked', + { id: 'original' }, + { + 'BentoReplace-propsOverride-unlocked': { + props: { + id: 'overridden', + className: 'custom-class' + } + } + }, + false + ); + + // data-slot="test" is added for slotted components (from main) + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); + + it('flags context and className with data-override when locked', function lockedPropsOverride() { + const html = renderWithEnvironment( + 'propsOverride-locked', + { id: 'original' }, + { + 'BentoReplace-propsOverride-locked': { + props: { + id: 'overridden', + className: 'custom-class' + } } - } - } - ); + }, + true + ); - assume(html).contains( - '
' - ); + // Context and className should both be flagged + assume(html).contains( + '
' + ); + }); }); - it('combines data-override values when component has existing overrides', function combinedOverrides() { - const html = createComponent( - 'combinedOverrides', - { style: { color: 'red' } }, - {}, - { - 'BentoReplace-combinedOverrides': function Component(props: any) { - assume(props['data-override']).equals('context style'); - return React.createElement('div', props); - } - } - ); - - assume(html).contains('
'); + describe('merging data-override values', function combinedOverrides() { + it('renders without data-override when unlocked', function unlockedNoMerge() { + const html = renderWithEnvironment( + 'combinedOverrides-unlocked', + { style: { color: 'red' } }, + { + 'BentoReplace-combinedOverrides-unlocked': function Component(props: any) { + assume(props['data-override']).equals(undefined); + return React.createElement('div', props); + } + }, + false + ); + + // data-slot="test" is added for slotted components (from main) + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); + + it('merges context and style into data-override when locked', function lockedMerge() { + const html = renderWithEnvironment( + 'combinedOverrides-locked', + { style: { color: 'red' } }, + { + 'BentoReplace-combinedOverrides-locked': function Component(props: any) { + assume(props['data-override']).equals('context style'); + return React.createElement('div', props); + } + }, + true + ); + + assume(html).contains('
'); + }); }); - it('handles falsy target components gracefully', function falsyTarget() { - const html = createComponent( - 'falsyTarget', - { id: 'example' }, - {}, - { - 'BentoReplace-falsyTarget': null - } - ); - - // Should render the original component without any replacement - assume(html).contains('
'); + describe('edge cases', function edgeCases() { + it('handles falsy target components without data-override when unlocked', function falsyTargetUnlocked() { + const html = renderWithEnvironment( + 'falsyTarget-unlocked', + { id: 'example' }, + { + 'BentoReplace-falsyTarget-unlocked': null + }, + false + ); + + // data-slot="test" is added for slotted components (from main) + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); + + it('handles falsy target components without data-override when locked', function falsyTargetLocked() { + const html = renderWithEnvironment( + 'falsyTarget-locked', + { id: 'example' }, + { + 'BentoReplace-falsyTarget-locked': null + }, + true + ); + + // data-slot="test" is added for slotted components (from main) + assume(html).contains('
'); + assume(html).does.not.contain('data-override'); + }); }); }); diff --git a/packages/slots/test/slots.node.test.ts b/packages/slots/test/slots.node.test.ts new file mode 100644 index 000000000..075fa39c2 --- /dev/null +++ b/packages/slots/test/slots.node.test.ts @@ -0,0 +1,314 @@ +import pkg from '../package.json' with { type: 'json' }; +import { dirname, resolve, join } from 'node:path'; +import { beforeEach, describe, it } from 'vitest'; +import { renderToString } from 'react-dom/server'; +import { withSlots, library } from '@bento/slots'; +import { Nested } from '../examples/nested.tsx'; +import { Box, defaults } from '@bento/box'; +import { Environment } from '@bento/environment'; +import { fileURLToPath } from 'node:url'; +import { useProps } from '@bento/use-props'; +import fs from 'node:fs/promises'; +import assume from 'assume'; +import React from 'react'; + +describe('@bento/slots', function bento() { + describe('withSlots', function slots() { + it('is a function', function fn() { + assume(withSlots).is.a('function'); + }); + + it('returns a Component with a displayName', function component() { + const Component = withSlots('Test', () => null); + assume(Component.displayName).equals('Slotted(Test)'); + }); + }); + + describe('library', function registration() { + beforeEach(function each() { + library.clear(); + }); + + it('is a set', function set() { + assume(library).is.a('set'); + assume(library.size).equals(0); + }); + + it('registers the component', function register() { + withSlots('example', () => null); + + assume(library.has('example')).is.true(); + }); + + it('throws a @bento/error when registering a duplicate name', function dupe() { + withSlots('example', () => null); + + assume(library.has('example')).is.true(); + assume(() => withSlots('example', () => null)).throws('@bento/slots(withSlots)'); + assume(() => withSlots('example', () => null)).throws('has already been registered.'); + + assume(library.size).equals(1); + }); + }); + + describe('slots', function nested() { + it('can render components without a `slot` property', function render() { + const Plain = withSlots('Plain', (props: any) => React.createElement('p', props, 'Hello World')); + const plain = renderToString(React.createElement(Plain, { id: 'example' })); + + assume(plain).contains('

Hello World

'); + }); + + it('renders the nested components', function render() { + const nested = renderToString(React.createElement(Nested, null)); + + assume(nested).contains('Hello World'); + assume(nested).contains('Click Me'); + }); + + it('uses dot notation to deeply affect slots', function override() { + const verify = assume.plan(6); + const nested = renderToString( + React.createElement(Nested, { + slots: { + 'example-container.label': function overrideLabel({ props, original }: any) { + assume(props.htmlFor).equals('example'); + assume(props.children).equals('Hello World'); + + assume(original.props.htmlFor).equals('example'); + assume(original.props.children).equals('Hello World'); + + return 'Overridden'; + } + } + }) + ); + + assume(nested).contains('Overridden'); + assume(nested).contains('Click Me'); + + verify(); + }); + + it('overrides the components used without introducing data-override when unlocked', function overrideUnlocked() { + let id: string | undefined; + + const nested = renderToString( + React.createElement(Environment, { + components: { + SlotsButton: function Button(props: any) { + assume(props['data-override']).equals(undefined); + assume(props.id).startsWith(':R'); + id = props.id; + + return React.createElement('p', props, 'No more button, only text'); + } + }, + children: React.createElement(Nested) + }) + ); + + assume(nested).contains('Hello World'); + assume(nested).does.not.contain('Click Me'); + // data-slot is added for slotted components (from main) + assume(nested).contains(`

No more button, only text

`); + }); + + it('flags component overrides with context when locked', function overrideLocked() { + let id: string | undefined; + + const nested = renderToString( + React.createElement(Environment, { + lock: true, + components: { + SlotsButton: function Button(props: any) { + assume(props['data-override']).equals('context'); + assume(props.id).startsWith(':R'); + id = props.id; + + return React.createElement('p', props, 'No more button, only text'); + } + }, + children: React.createElement(Nested) + }) + ); + + assume(nested).contains('Hello World'); + assume(nested).does.not.contain('Click Me'); + // data-slot is added for slotted components (from main) + assume(nested).contains(`

No more button, only text

`); + }); + }); + + describe('generation tracking', function generationTracking() { + it('verifies generation tracking is initialized', function initialization() { + const ctx = defaults(); + + // Check that generation tracking properties exist + assume(ctx.env.lockGeneration).equals(0); + assume(ctx.env.locked).equals(false); + assume(ctx.slots.slotGenerations).is.a('object'); + }); + + it('slots are correctly applied and tracked when locked', function applicationLocked() { + const Child = withSlots('TrackChild', function TrackChildComponent(args: any) { + const { props } = useProps(args); + return React.createElement('span', props, 'child'); + }); + + const Parent = withSlots('TrackParent', function TrackParentComponent(props: any) { + return React.createElement('div', props, React.createElement(Child, { slot: 'child' })); + }); + + const html = renderToString( + React.createElement(Environment, { + lock: true, + children: React.createElement(Parent, { + slot: 'parent', + slots: { child: { className: 'tracked' } } + }) + }) + ); + + // Verify slot is applied. Since the slots are passed INSIDE the locked environment + // (internal composition), they should NOT trigger data-override. + // data-slot is added for slotted components (from main) + assume(html).does.not.contain('data-override'); + assume(html).contains('data-slot="child"'); + assume(html).contains('class="tracked"'); + assume(html).contains('child'); + }); + + it('does not flag slot tracking when environment is unlocked', function applicationUnlocked() { + const Child = withSlots('TrackChildUnlocked', function TrackChildComponent(props: any) { + return React.createElement('span', props, 'child'); + }); + + const Parent = withSlots('TrackParentUnlocked', function TrackParentComponent(props: any) { + return React.createElement('div', props, React.createElement(Child, { slot: 'child' })); + }); + + const html = renderToString( + React.createElement(Environment, { + children: React.createElement(Parent, { + slot: 'parent', + slots: { child: { className: 'tracked' } } + }) + }) + ); + + // data-slot is added for slotted components (from main) + assume(html).contains(''); + assume(html).does.not.contain('data-override'); + }); + + it('generation tracking does not break existing functionality', function noBreakage() { + const Component = withSlots('NoBreakTest', function NoBreakTestComponent(props: any) { + return React.createElement('div', props, props.children); + }); + + const ctx = defaults(); + + const html = renderToString( + React.createElement( + Box.Provider, + { value: ctx }, + React.createElement( + Component, + { + id: 'test', + className: 'example' + }, + 'content' + ) + ) + ); + + // Verify normal rendering works + assume(html).contains('id="test"'); + assume(html).contains('class="example"'); + assume(html).contains('content'); + }); + }); + + describe('modifiers', function modifiers() { + it('allows custom modifiers to be passed', function custom() { + let ran = false; + + function Custom() { + return null; + } + + function modifier(data: any) { + assume(data).is.a('object'); + assume(data.props).is.a('object'); + assume(data.props.id).equals('example'); + // Custom is wrapped with forwardRef since it has 0 parameters (length !== 1) + // so data.Component will be the wrapped version, not the original + assume(data.Component).exist(); + + assume(data.context.env).is.a('object'); + assume(data.context.slots).is.a('object'); + assume(data.context.slots.assigned).is.a('object'); + assume(data.context.slots.namespace).is.a('array'); + assume(data.context.slots.override).is.false(); + assume(data.context.env.components).is.a('object'); + + assume(data.name).equals('CustomNameHere'); + + ran = true; + } + + const Component: any = withSlots('CustomNameHere', Custom, [modifier as any]); + + renderToString(React.createElement(Component, { id: 'example' })); + assume(ran).is.true(); + }); + + it('throws when the modifier is not a function', function invalid() { + let index = 0; + function trigger() { + withSlots('InvalidModifier' + index++, () => null, [{} as any]); + } + + assume(trigger).throws('@bento/slots(withSlots)'); + assume(trigger).throws('The supplied component modifier is not a function.'); + assume(trigger).throws('https://example.com/docs/errors/#9F4D92'); + }); + }); + + describe('Public API', function packageSuite() { + const __dirname = dirname(fileURLToPath(import.meta.url)); + + describe('#exports', function exportsSuite() { + Object.keys(pkg.exports).forEach(function each(subpaths) { + describe(`${subpaths}`, function subpathsSuite() { + const exportPath = (pkg.exports as any)[subpaths]; + + if (typeof exportPath === 'string') { + return it(`exports ${subpaths} exists`, async function exportedTest() { + const path = resolve(__dirname, '..', exportPath); + await fs.access(path, fs.constants.F_OK); + }); + } + + Object.keys(exportPath).forEach(function each(exported) { + if (typeof exportPath[exported] === 'string') { + it(`conditional export "${exported}" exists for ${join(pkg.name, subpaths)}`, async function exportedTest() { + const path = resolve(__dirname, '..', exportPath[exported]); + await fs.access(path, fs.constants.F_OK); + }); + } else { + Object.keys(exportPath[exported]).forEach(function each(key) { + it(`conditional export "${exported}.${key}" exists for ${join(pkg.name, subpaths)}`, async function exportedTest() { + const path = resolve(__dirname, '..', exportPath[exported][key]); + await fs.access(path, fs.constants.F_OK); + }); + }); + } + }); + }); + }); + }); + }); +}); diff --git a/packages/slots/test/slots.node.test.tsx b/packages/slots/test/slots.node.test.tsx index 9a30fa96e..c2d6236b0 100644 --- a/packages/slots/test/slots.node.test.tsx +++ b/packages/slots/test/slots.node.test.tsx @@ -94,6 +94,9 @@ describe('@bento/slots', function bento() { let id; const value = defaults(); + // Set locked: true to trigger data-override behavior + value.env.locked = true; + value.env.lockGeneration = 1; value.env.components = { SlotsButton: function Button(props) { assume(props['data-override']).equals('context'); @@ -112,6 +115,7 @@ describe('@bento/slots', function bento() { assume(nested).contains('Hello World'); assume(nested).does.not.contain('Click Me'); + // data-slot is added for slotted components (from main) assume(nested).contains(`

No more button, only text

`); }); }); diff --git a/packages/slots/vitest.config.ts b/packages/slots/vitest.config.ts index 2fc5573b2..08967ea2d 100644 --- a/packages/slots/vitest.config.ts +++ b/packages/slots/vitest.config.ts @@ -6,7 +6,15 @@ export default mergeConfig( defineConfig({ test: { coverage: { - exclude: ['src/index.ts'] + exclude: ['src/index.ts'], + thresholds: { + 'src/**.{ts,tsx}': { + statements: 90, + functions: 100, + branches: 90, + lines: 95 + } + } }, projects: [ssr, browser] } diff --git a/packages/svg-parser/tsup.config.bundled_30o7dkbsddx.mjs b/packages/svg-parser/tsup.config.bundled_30o7dkbsddx.mjs new file mode 100644 index 000000000..507044a3d --- /dev/null +++ b/packages/svg-parser/tsup.config.bundled_30o7dkbsddx.mjs @@ -0,0 +1,22 @@ +// ../../configs/tsup.config.mts +import browserslistToEsbuild from "browserslist-to-esbuild"; +var shared = { + format: ["esm", "cjs"], + sourcemap: true, + clean: true, + treeshake: true, + loader: { ".css": "copy" }, + target: browserslistToEsbuild(), + dts: true +}; + +// tsup.config.ts +import { defineConfig } from "tsup"; +var tsup_config_default = defineConfig({ + ...shared, + entry: ["src/index.ts"] +}); +export { + tsup_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vY29uZmlncy90c3VwLmNvbmZpZy5tdHMiLCAidHN1cC5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9faW5qZWN0ZWRfZmlsZW5hbWVfXyA9IFwiL1ZvbHVtZXMvUHJvamVjdHMvZ29kYWRkeS9iZW50by9jb25maWdzL3RzdXAuY29uZmlnLm10c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVm9sdW1lcy9Qcm9qZWN0cy9nb2RhZGR5L2JlbnRvL2NvbmZpZ3NcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1ZvbHVtZXMvUHJvamVjdHMvZ29kYWRkeS9iZW50by9jb25maWdzL3RzdXAuY29uZmlnLm10c1wiO2ltcG9ydCB7IHR5cGUgT3B0aW9ucyB9IGZyb20gJ3RzdXAnO1xuaW1wb3J0IGJyb3dzZXJzbGlzdFRvRXNidWlsZCBmcm9tICdicm93c2Vyc2xpc3QtdG8tZXNidWlsZCc7XG5cbmV4cG9ydCBjb25zdCBzaGFyZWQ6IE9wdGlvbnMgPSB7XG4gIGZvcm1hdDogWydlc20nLCAnY2pzJ10sXG4gIHNvdXJjZW1hcDogdHJ1ZSxcbiAgY2xlYW46IHRydWUsXG4gIHRyZWVzaGFrZTogdHJ1ZSxcbiAgbG9hZGVyOiB7ICcuY3NzJzogJ2NvcHknIH0sXG4gIHRhcmdldDogYnJvd3NlcnNsaXN0VG9Fc2J1aWxkKCksXG4gIGR0czogdHJ1ZVxufTtcbiIsICJjb25zdCBfX2luamVjdGVkX2ZpbGVuYW1lX18gPSBcIi9Wb2x1bWVzL1Byb2plY3RzL2dvZGFkZHkvYmVudG8vcGFja2FnZXMvc3ZnLXBhcnNlci90c3VwLmNvbmZpZy50c1wiO2NvbnN0IF9faW5qZWN0ZWRfZGlybmFtZV9fID0gXCIvVm9sdW1lcy9Qcm9qZWN0cy9nb2RhZGR5L2JlbnRvL3BhY2thZ2VzL3N2Zy1wYXJzZXJcIjtjb25zdCBfX2luamVjdGVkX2ltcG9ydF9tZXRhX3VybF9fID0gXCJmaWxlOi8vL1ZvbHVtZXMvUHJvamVjdHMvZ29kYWRkeS9iZW50by9wYWNrYWdlcy9zdmctcGFyc2VyL3RzdXAuY29uZmlnLnRzXCI7aW1wb3J0IHsgc2hhcmVkIH0gZnJvbSAnLi4vLi4vY29uZmlncy90c3VwLmNvbmZpZy5tdHMnO1xuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndHN1cCc7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIC4uLnNoYXJlZCxcbiAgZW50cnk6IFsnc3JjL2luZGV4LnRzJ11cbn0pO1xuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUNBLE9BQU8sMkJBQTJCO0FBRTNCLElBQU0sU0FBa0I7QUFBQSxFQUM3QixRQUFRLENBQUMsT0FBTyxLQUFLO0FBQUEsRUFDckIsV0FBVztBQUFBLEVBQ1gsT0FBTztBQUFBLEVBQ1AsV0FBVztBQUFBLEVBQ1gsUUFBUSxFQUFFLFFBQVEsT0FBTztBQUFBLEVBQ3pCLFFBQVEsc0JBQXNCO0FBQUEsRUFDOUIsS0FBSztBQUNQOzs7QUNWQSxTQUFTLG9CQUFvQjtBQUU3QixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMxQixHQUFHO0FBQUEsRUFDSCxPQUFPLENBQUMsY0FBYztBQUN4QixDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo= diff --git a/packages/text/test/text.node.test.tsx b/packages/text/test/text.node.test.tsx index 0306b54f7..185206e5c 100644 --- a/packages/text/test/text.node.test.tsx +++ b/packages/text/test/text.node.test.tsx @@ -78,18 +78,6 @@ describe('@bento/text', function bento() { assume(result).includes('--wrap:pretty'); }); - describe('#slots', function slots() { - it('renders correct [data-override] attribute values', function dataOverride() { - const result = renderToStringText({ - className: 'custom-class', - style: { color: 'red' }, - children: 'Handgloves' - }); - - assume(result).includes('data-override="className style"'); - }); - }); - describe('Public API', function packageSuite() { const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/packages/use-props/package.json b/packages/use-props/package.json index b368171dd..0d7f46b22 100644 --- a/packages/use-props/package.json +++ b/packages/use-props/package.json @@ -42,7 +42,6 @@ ], "dependencies": { "@bento/box": "^0.2.0", - "@bento/internal-props": "^0.1.1", "@bento/types": "^0.1.0", "@react-aria/utils": "^3.30.0" }, diff --git a/packages/use-props/src/index.ts b/packages/use-props/src/index.ts index 5ec69bb3f..d2bdc35f7 100644 --- a/packages/use-props/src/index.ts +++ b/packages/use-props/src/index.ts @@ -1,5 +1,4 @@ import { Box, type BoxContext } from '@bento/box'; -import { useInternalProps } from '@bento/internal-props'; import { AnyObject } from '@bento/types'; import { mergeRefs } from '@react-aria/utils'; import { useContext } from 'react'; @@ -100,9 +99,9 @@ function mergeRefList(refs: Array | Ref | undefined>): Re export interface Returns { /** - * Proxy object that have access to the original props, slotted values, and internal props. When - * accessing a property, it will first check the slotted values, then the original props, and finally - * the internal props. If the property is a render prop, it will execute the function with the provided + * Proxy object that have access to the original props and slotted values. When + * accessing a property, it will first check the slotted values, then the original props. + * If the property is a render prop, it will execute the function with the provided * arguments. * * @default { ...props, ...slots } @@ -157,7 +156,7 @@ export function useProps(...rest: any[]): Returns { } const { slots } = useContext>(Box); - const [props, internal] = useInternalProps(args); + const props = args; const { namespace, assigned } = slots; const dot = namespace.join('.'); const slotted = assigned[dot] || {}; @@ -174,7 +173,7 @@ export function useProps(...rest: any[]): Returns { delete slotNoRef.ref; delete propsNoRef.ref; - const propsy: AnyObject = { ...internal, ...propsNoRef, ...slotNoRef }; + const propsy: AnyObject = { ...propsNoRef, ...slotNoRef }; /** * Applies the given attributes to an object. @@ -192,7 +191,7 @@ export function useProps(...rest: any[]): Returns { if (except && except.includes(key)) return memo; memo[key] = renderProp(key, { - props: { ...props, ...internal }, + props, original: data[key], slots: slotted, state @@ -220,7 +219,7 @@ export function useProps(...rest: any[]): Returns { return renderProp(name, { original: isRenderProp(name, props[name]) ? undefined : props[name], - props: { ...props, ...internal }, + props, slots: slotted, state }); diff --git a/packages/use-props/test/__snapshots__/examples.browser.test.tsx.snap b/packages/use-props/test/__snapshots__/examples.browser.test.tsx.snap new file mode 100644 index 000000000..4fa7aeb33 --- /dev/null +++ b/packages/use-props/test/__snapshots__/examples.browser.test.tsx.snap @@ -0,0 +1,17 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`@bento/use-props examples > Apply Button > should handle additional props correctly 1`] = `""`; + +exports[`@bento/use-props examples > Apply Button > should render a button with applied className 1`] = `""`; + +exports[`@bento/use-props examples > Apply and Omit Button > should handle props correctly 1`] = `""`; + +exports[`@bento/use-props examples > Apply and Omit Button > should render a button with applied className and omitted props 1`] = `""`; + +exports[`@bento/use-props examples > Basic Button > can be rendered as an anchor with className 1`] = `"Click this link"`; + +exports[`@bento/use-props examples > Basic Button > should render a button without a className 1`] = `""`; + +exports[`@bento/use-props examples > Memo > should render a memoized button 1`] = `"This button has a different class Name"`; + +exports[`@bento/use-props examples > Nested > renders the changes from a slot assignment 1`] = `"
Click Me
"`; diff --git a/packages/use-props/test/examples.browser.test.tsx b/packages/use-props/test/examples.browser.test.tsx index 937c7f61b..2bfaddb21 100644 --- a/packages/use-props/test/examples.browser.test.tsx +++ b/packages/use-props/test/examples.browser.test.tsx @@ -4,19 +4,14 @@ import { Button as BasicButton } from '../examples/button.tsx'; import { Nested } from '../examples/nested.tsx'; import { Memo } from '../examples/memo.tsx'; import { render } from 'vitest-browser-react'; -import { describe, it } from 'vitest'; -import assume from 'assume'; +import { describe, it, expect } from 'vitest'; import React from 'react'; describe('@bento/use-props examples', function bento() { describe('Basic Button', function button() { it('should render a button without a className', function test() { const { container } = render(Click this button); - const result = container.innerHTML; - - assume(result).includes('button'); - assume(result).includes('Click this button'); - assume(result).does.not.includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); it('can be rendered as an anchor with className', function test() { @@ -25,25 +20,14 @@ describe('@bento/use-props examples', function bento() { Click this link ); - const result = container.innerHTML; - - assume(result).does.not.includes('button'); - assume(result).startsWith(''); - assume(result).includes('href="foo.bar"'); - assume(result).includes('Click this link'); - assume(result).includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('Apply Button', function applyButton() { it('should render a button with applied className', function test() { const { container } = render(Click this button); - const result = container.innerHTML; - - assume(result).includes('button'); - assume(result).includes('Click this button'); - assume(result).includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); it('should handle additional props correctly', function test() { @@ -52,23 +36,14 @@ describe('@bento/use-props examples', function bento() { Click this button ); - const result = container.innerHTML; - - assume(result).includes('button'); - assume(result).includes('data-testid="test"'); - assume(result).includes('disabled'); - assume(result).includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('Apply and Omit Button', function applyOmitButton() { it('should render a button with applied className and omitted props', function test() { const { container } = render(Click this button); - const result = container.innerHTML; - - assume(result).includes('button'); - assume(result).includes('Click this button'); - assume(result).includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); it('should handle props correctly', function test() { @@ -77,24 +52,14 @@ describe('@bento/use-props examples', function bento() { Click this link ); - const result = container.innerHTML; - - assume(result).includes('button'); - assume(result).includes('data-testid="test"'); - assume(result).includes('href="test.com"'); - assume(result).includes('class="xyz-hashed-class"'); + expect(container.innerHTML).toMatchSnapshot(); }); }); describe('Memo', function memo() { it('should render a memoized button', function test() { const { container } = render(); - const result = container.innerHTML; - - assume(result).includes('href="https://example.com" target="_blank"'); - assume(result).includes('This button has a different class Name'); - assume(result).includes('class="xyz-hashed-class my-className my-class"'); - assume(result).includes('data-override="className"'); + expect(container.innerHTML).toMatchSnapshot(); }); }); @@ -114,11 +79,7 @@ describe('@bento/use-props examples', function bento() { }} /> ); - - const result = container.innerHTML; - assume(result).includes('Click Me'); - assume(result).includes('href="https://example.com"'); - assume(result).includes('class="xyz-hashed-class button"'); + expect(container.innerHTML).toMatchSnapshot(); }); }); }); diff --git a/packages/use-props/test/use-props.node.test.tsx b/packages/use-props/test/use-props.node.test.tsx index d32fdfbba..7b6ca7b7e 100644 --- a/packages/use-props/test/use-props.node.test.tsx +++ b/packages/use-props/test/use-props.node.test.tsx @@ -136,7 +136,7 @@ describe('@bento/use-props', function bento() { * @property {function} apply - The apply function returned by useProps. * @private */ - function createComponent(name: string, props = {}, slots = {}) { + function createComponent(name: string, props = {}, slots = {}, locked = false) { let result: any; const TestReturn = withSlots(`BentoRenderProps-${name}`, function Component(args) { @@ -150,6 +150,14 @@ describe('@bento/use-props', function bento() { context.slots.namespace = []; context.slots.override = false; + // Set up locked environment if requested + if (locked) { + context.env.locked = true; + context.env.lockGeneration = 1; + // Mark the slot as from an earlier generation (before lock) + context.slots.slotGenerations = { test: 0 }; + } + return { html: renderToString( React.createElement( @@ -239,6 +247,25 @@ describe('@bento/use-props', function bento() { assume(props.title).equals('my title'); }); + + it('merges slot props directly without internal-props separation', function noInternalProps() { + const { props } = createComponent( + 'no-internal', + { + id: 'component', + className: 'from-props' + }, + { + className: 'from-slot', + 'data-test': 'slot-data' + } + ); + + // Slot values should override component props directly + assume(props.id).equals('component'); + assume(props.className).equals('from-slot'); + assume(props['data-test']).equals('slot-data'); + }); }); describe('apply', function applying() { @@ -279,7 +306,8 @@ describe('@bento/use-props', function bento() { }, { id: 'modified' - } + }, + true // locked environment to trigger data-override ); const result = apply(); @@ -321,7 +349,8 @@ describe('@bento/use-props', function bento() { }, { id: 'modified' - } + }, + true // locked environment to trigger data-override ); const result = apply({ id: 'hello-there' });